diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Financial Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Financial Agent.json index f137f5b2a..7d0fa52ad 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Financial Agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Financial Agent.json @@ -606,9 +606,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": false, - "type": "ChatInput", - "selected_output": "message" + "type": "ChatInput" }, "dragging": false, "id": "ChatInput-X83ni", @@ -1073,9 +1073,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "TavilySearchComponent", - "selected_output": "component_as_tool" + "type": "TavilySearchComponent" }, "dragging": false, "id": "TavilySearchComponent-7Y3yy", @@ -1323,9 +1323,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "YfinanceComponent", - "selected_output": "component_as_tool" + "type": "YfinanceComponent" }, "dragging": false, "id": "YfinanceComponent-KpeWR", @@ -2062,9 +2062,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "URL", - "selected_output": "component_as_tool" + "type": "URL" }, "dragging": false, "id": "URL-N9CXl", @@ -2412,9 +2412,9 @@ }, "tool_mode": false }, + "selected_output": "text_output", "showNode": true, - "type": "SambaNovaModel", - "selected_output": "text_output" + "type": "SambaNovaModel" }, "dragging": false, "id": "SambaNovaModel-NEyqD", @@ -2636,7 +2636,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -3188,9 +3188,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-cGZsD", @@ -3272,7 +3272,7 @@ } ], "pinned": false, - "score": 5.283996070936036e-07, + "score": 5.283996070936036e-7, "template": { "_type": "Component", "add_current_date_tool": { @@ -3412,7 +3412,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -3964,9 +3964,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-wqbpC", @@ -4142,9 +4142,9 @@ }, "tool_mode": false }, + "selected_output": "prompt", "showNode": true, - "type": "Prompt", - "selected_output": "prompt" + "type": "Prompt" }, "dragging": false, "id": "Prompt-er8QV", @@ -4320,9 +4320,9 @@ }, "tool_mode": false }, + "selected_output": "prompt", "showNode": true, - "type": "Prompt", - "selected_output": "prompt" + "type": "Prompt" }, "dragging": false, "id": "Prompt-AdpTy", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Gmail Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Gmail Agent.json index 9d2502778..0405f3f45 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Gmail Agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Gmail Agent.json @@ -267,7 +267,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -811,9 +811,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-BxJm3", @@ -1125,9 +1125,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": false, - "type": "ChatInput", - "selected_output": "message" + "type": "ChatInput" }, "dragging": false, "id": "ChatInput-buyiB", @@ -2942,9 +2942,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "GmailAPI", - "selected_output": "component_as_tool" + "type": "GmailAPI" }, "dragging": false, "id": "GmailAPI-J65iP", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json b/src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json index 7aca17fda..f8c36fdc7 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json @@ -564,8 +564,8 @@ } } }, - "type": "ChatInput", - "selected_output": "message" + "selected_output": "message", + "type": "ChatInput" }, "dragging": false, "height": 234, @@ -742,8 +742,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 433, @@ -848,8 +848,8 @@ } } }, - "type": "TextInput", - "selected_output": "text" + "selected_output": "text", + "type": "TextInput" }, "dragging": false, "height": 234, @@ -1002,8 +1002,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 347, @@ -1497,7 +1497,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -1997,8 +1997,8 @@ }, "tool_mode": false }, - "type": "Agent", - "selected_output": "response" + "selected_output": "response", + "type": "Agent" }, "dragging": false, "height": 650, @@ -2175,8 +2175,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 433, @@ -2811,9 +2811,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "TavilySearchComponent", - "selected_output": "component_as_tool" + "type": "TavilySearchComponent" }, "dragging": false, "id": "TavilySearchComponent-HW6b0", @@ -3201,9 +3201,9 @@ }, "tool_mode": false }, + "selected_output": "text_output", "showNode": true, - "type": "OpenAIModel", - "selected_output": "text_output" + "type": "OpenAIModel" }, "dragging": false, "id": "OpenAIModel-dqLbl", @@ -3591,9 +3591,9 @@ }, "tool_mode": false }, + "selected_output": "text_output", "showNode": true, - "type": "OpenAIModel", - "selected_output": "text_output" + "type": "OpenAIModel" }, "dragging": false, "id": "OpenAIModel-7yVxU", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json b/src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json index 3f5f23503..f1ff5b9c9 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json @@ -259,9 +259,9 @@ }, "tool_mode": false }, + "selected_output": "prompt", "showNode": true, - "type": "Prompt", - "selected_output": "prompt" + "type": "Prompt" }, "dragging": false, "id": "Prompt-0aGkQ", @@ -688,7 +688,7 @@ } ], "pinned": false, - "score": 7.568328950209746e-06, + "score": 7.568328950209746e-6, "template": { "_type": "Component", "code": { @@ -824,9 +824,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "needle", - "selected_output": "component_as_tool" + "type": "needle" }, "id": "needle-5GYmd", "measured": { @@ -1136,9 +1136,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": true, - "type": "ChatInput", - "selected_output": "message" + "type": "ChatInput" }, "dragging": false, "id": "ChatInput-cKEM6", @@ -1359,7 +1359,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -1923,9 +1923,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "id": "Agent-DBNrp", "measured": { diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Market Research.json b/src/backend/base/langflow/initial_setup/starter_projects/Market Research.json index 3f5256f36..3a2cd2bf4 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Market Research.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Market Research.json @@ -1315,7 +1315,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json b/src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json index 29f224e15..3c5496cda 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json @@ -561,9 +561,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "AgentQL", - "selected_output": "component_as_tool" + "type": "AgentQL" }, "dragging": false, "id": "AgentQL-TCADj", @@ -875,9 +875,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": false, - "type": "ChatInput", - "selected_output": "message" + "type": "ChatInput" }, "dragging": false, "id": "ChatInput-LwqUD", @@ -1095,7 +1095,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -1639,9 +1639,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-x50rv", @@ -2133,9 +2133,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": false, - "type": "ChatOutput", - "selected_output": "message" + "type": "ChatOutput" }, "dragging": false, "id": "ChatOutput-RB2DM", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json index 769951a37..05dd7d495 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json @@ -383,9 +383,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": false, - "type": "ChatInput", - "selected_output": "message" + "type": "ChatInput" }, "dragging": false, "id": "ChatInput-ZNO2E", @@ -1247,9 +1247,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "APIRequest", - "selected_output": "component_as_tool" + "type": "APIRequest" }, "dragging": false, "id": "APIRequest-Yr0ij", @@ -1470,7 +1470,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -2019,9 +2019,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-iU8sJ", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json b/src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json index daef45b9a..0d4961258 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json @@ -413,9 +413,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": false, - "type": "ChatInput", - "selected_output": "message" + "type": "ChatInput" }, "dragging": false, "id": "ChatInput-DwzkZ", @@ -1178,9 +1178,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "TavilySearchComponent", - "selected_output": "component_as_tool" + "type": "TavilySearchComponent" }, "dragging": false, "id": "TavilySearchComponent-STQC5", @@ -1586,9 +1586,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "AgentQL", - "selected_output": "component_as_tool" + "type": "AgentQL" }, "dragging": false, "id": "AgentQL-reBlu", @@ -1778,7 +1778,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -2322,9 +2322,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-oRYZX", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json index 38e28f856..8b46a2ddf 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json @@ -420,8 +420,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 347, @@ -718,8 +718,8 @@ } } }, - "type": "ChatInput", - "selected_output": "message" + "selected_output": "message", + "type": "ChatInput" }, "dragging": false, "height": 234, @@ -896,8 +896,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 433, @@ -1126,7 +1126,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -1626,8 +1626,8 @@ }, "tool_mode": false }, - "type": "Agent", - "selected_output": "response" + "selected_output": "response", + "type": "Agent" }, "dragging": false, "height": 658, @@ -1755,8 +1755,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 260, @@ -1884,8 +1884,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 260, @@ -2386,9 +2386,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "TavilySearchComponent", - "selected_output": "component_as_tool" + "type": "TavilySearchComponent" }, "dragging": false, "id": "TavilySearchComponent-okHYL", @@ -2776,9 +2776,9 @@ }, "tool_mode": false }, + "selected_output": "text_output", "showNode": true, - "type": "OpenAIModel", - "selected_output": "text_output" + "type": "OpenAIModel" }, "dragging": false, "id": "OpenAIModel-sO8rf", @@ -3166,9 +3166,9 @@ }, "tool_mode": false }, + "selected_output": "text_output", "showNode": true, - "type": "OpenAIModel", - "selected_output": "text_output" + "type": "OpenAIModel" }, "dragging": false, "id": "OpenAIModel-1pnlf", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json b/src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json index 1b253bf34..3ef1055ce 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json @@ -313,8 +313,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 693, @@ -845,7 +845,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -1345,8 +1345,8 @@ }, "tool_mode": false }, - "type": "Agent", - "selected_output": "response" + "selected_output": "response", + "type": "Agent" }, "dragging": false, "height": 650, @@ -1541,9 +1541,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "CalculatorComponent", - "selected_output": "component_as_tool" + "type": "CalculatorComponent" }, "dragging": false, "id": "CalculatorComponent-LyoFm", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Search agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Search agent.json index eacef4e6e..2af451508 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Search agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Search agent.json @@ -290,9 +290,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "ScrapeGraphSearchApi", - "selected_output": "component_as_tool" + "type": "ScrapeGraphSearchApi" }, "dragging": false, "id": "ScrapeGraphSearchApi-vo1Yo", @@ -600,9 +600,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": false, - "type": "ChatInput", - "selected_output": "message" + "type": "ChatInput" }, "dragging": false, "id": "ChatInput-v88Su", @@ -1073,7 +1073,7 @@ } ], "pinned": false, - "score": 5.283996070936036e-07, + "score": 5.283996070936036e-7, "template": { "_type": "Component", "add_current_date_tool": { @@ -1212,7 +1212,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -1758,9 +1758,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-xgcha", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json b/src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json index daee50bf4..da408a357 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json @@ -486,7 +486,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -986,8 +986,8 @@ }, "tool_mode": false }, - "type": "Agent", - "selected_output": "response" + "selected_output": "response", + "type": "Agent" }, "dragging": false, "height": 650, @@ -1179,7 +1179,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -1679,8 +1679,8 @@ }, "tool_mode": false }, - "type": "Agent", - "selected_output": "response" + "selected_output": "response", + "type": "Agent" }, "dragging": false, "height": 650, @@ -1814,8 +1814,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 260, @@ -1949,8 +1949,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 260, @@ -2133,8 +2133,8 @@ }, "tool_mode": false }, - "type": "Prompt", - "selected_output": "prompt" + "selected_output": "prompt", + "type": "Prompt" }, "dragging": false, "height": 433, @@ -2437,8 +2437,8 @@ }, "tool_mode": false }, - "type": "ChatInput", - "selected_output": "message" + "selected_output": "message", + "type": "ChatInput" }, "dragging": false, "height": 234, @@ -2702,7 +2702,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -3202,8 +3202,8 @@ }, "tool_mode": false }, - "type": "Agent", - "selected_output": "response" + "selected_output": "response", + "type": "Agent" }, "dragging": false, "height": 650, @@ -3577,9 +3577,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "YfinanceComponent", - "selected_output": "component_as_tool" + "type": "YfinanceComponent" }, "dragging": true, "id": "YfinanceComponent-Adjq6", @@ -3767,9 +3767,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "CalculatorComponent", - "selected_output": "component_as_tool" + "type": "CalculatorComponent" }, "dragging": false, "id": "CalculatorComponent-9O7Ap", @@ -4232,9 +4232,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "TavilySearchComponent", - "selected_output": "component_as_tool" + "type": "TavilySearchComponent" }, "dragging": false, "id": "TavilySearchComponent-6ezaX", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json index ade56b654..70e950aa3 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json @@ -525,8 +525,8 @@ }, "tool_mode": true }, - "type": "URL", - "selected_output": "component_as_tool" + "selected_output": "component_as_tool", + "type": "URL" }, "dragging": false, "id": "URL-o7GEq", @@ -722,9 +722,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "CalculatorComponent", - "selected_output": "component_as_tool" + "type": "CalculatorComponent" }, "dragging": false, "id": "CalculatorComponent-15FSE", @@ -1036,9 +1036,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": false, - "type": "ChatInput", - "selected_output": "message" + "type": "ChatInput" }, "dragging": false, "id": "ChatInput-2YUmA", @@ -1568,7 +1568,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -2117,9 +2117,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-qYZ9W", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json index e272d1632..34b18339b 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json @@ -303,9 +303,9 @@ }, "tool_mode": false }, + "selected_output": "tool", "showNode": true, - "type": "ApifyActors", - "selected_output": "tool" + "type": "ApifyActors" }, "dragging": false, "id": "ApifyActors-t44sy", @@ -506,9 +506,9 @@ }, "tool_mode": false }, + "selected_output": "tool", "showNode": true, - "type": "ApifyActors", - "selected_output": "tool" + "type": "ApifyActors" }, "dragging": false, "id": "ApifyActors-n0Tjo", @@ -901,9 +901,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": false, - "type": "ChatInput", - "selected_output": "message" + "type": "ChatInput" }, "dragging": false, "id": "ChatInput-9joxW", @@ -1457,7 +1457,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -2003,9 +2003,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-EePDq", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json b/src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json index 9ae235d35..72b2596dd 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json @@ -470,8 +470,8 @@ } } }, - "type": "ChatInput", - "selected_output": "message" + "selected_output": "message", + "type": "ChatInput" }, "dragging": false, "height": 262, @@ -1389,9 +1389,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "URL", - "selected_output": "component_as_tool" + "type": "URL" }, "dragging": false, "id": "URL-4LSRv", @@ -1536,9 +1536,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "CalculatorComponent", - "selected_output": "component_as_tool" + "type": "CalculatorComponent" }, "dragging": false, "id": "CalculatorComponent-hlWP4", @@ -1801,9 +1801,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "SearchComponent", - "selected_output": "component_as_tool" + "type": "SearchComponent" }, "dragging": false, "id": "SearchComponent-kgsWf", @@ -2024,7 +2024,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -2570,9 +2570,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-H916j", @@ -2793,7 +2793,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -3339,9 +3339,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-zFKST", @@ -3562,7 +3562,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -4108,9 +4108,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-3tuWs", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json b/src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json index 338e9327d..c7bec11c1 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json @@ -508,9 +508,9 @@ }, "tool_mode": false }, + "selected_output": "batch_results", "showNode": true, - "type": "BatchRunComponent", - "selected_output": "batch_results" + "type": "BatchRunComponent" }, "dragging": false, "id": "BatchRunComponent-kxOUU", @@ -714,9 +714,9 @@ }, "tool_mode": false }, + "selected_output": "comments", "showNode": true, - "type": "YouTubeCommentsComponent", - "selected_output": "comments" + "type": "YouTubeCommentsComponent" }, "dragging": false, "id": "YouTubeCommentsComponent-g4VZV", @@ -1105,9 +1105,9 @@ }, "tool_mode": false }, + "selected_output": "model_output", "showNode": true, - "type": "OpenAIModel", - "selected_output": "model_output" + "type": "OpenAIModel" }, "dragging": false, "id": "OpenAIModel-0iBkZ", @@ -1297,7 +1297,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n\n # Validate tools\n # if not self.tools:\n # msg = \"Tools are required to run the agent. Please add at least one tool.\"\n # raise ValueError(msg)\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" + "value": "from langchain_core.tools import StructuredTool\n\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.base.agents.events import ExceptionWithMessageError\nfrom langflow.base.models.model_input_constants import (\n ALL_PROVIDER_FIELDS,\n MODEL_DYNAMIC_UPDATE_FIELDS,\n MODEL_PROVIDERS_DICT,\n MODELS_METADATA,\n)\nfrom langflow.base.models.model_utils import get_model_name\nfrom langflow.components.helpers.current_date import CurrentDateComponent\nfrom langflow.components.helpers.memory import MemoryComponent\nfrom langflow.components.langchain_utilities.tool_calling import ToolCallingAgentComponent\nfrom langflow.custom.custom_component.component import _get_component_toolkit\nfrom langflow.custom.utils import update_component_build_config\nfrom langflow.field_typing import Tool\nfrom langflow.io import BoolInput, DropdownInput, MultilineInput, Output\nfrom langflow.logging import logger\nfrom langflow.schema.dotdict import dotdict\nfrom langflow.schema.message import Message\n\n\ndef set_advanced_true(component_input):\n component_input.advanced = True\n return component_input\n\n\nclass AgentComponent(ToolCallingAgentComponent):\n display_name: str = \"Agent\"\n description: str = \"Define the agent's instructions, then enter a task to complete using tools.\"\n icon = \"bot\"\n beta = False\n name = \"Agent\"\n\n memory_inputs = [set_advanced_true(component_input) for component_input in MemoryComponent().inputs]\n\n inputs = [\n DropdownInput(\n name=\"agent_llm\",\n display_name=\"Model Provider\",\n info=\"The provider of the language model that the agent will use to generate responses.\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"OpenAI\",\n real_time_refresh=True,\n input_types=[],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())] + [{\"icon\": \"brain\"}],\n ),\n *MODEL_PROVIDERS_DICT[\"OpenAI\"][\"inputs\"],\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Agent Instructions\",\n info=\"System Prompt: Initial instructions and context provided to guide the agent's behavior.\",\n value=\"You are a helpful assistant that can use tools to answer questions and perform tasks.\",\n advanced=False,\n ),\n *LCToolsAgentComponent._base_inputs,\n *memory_inputs,\n BoolInput(\n name=\"add_current_date_tool\",\n display_name=\"Current Date\",\n advanced=True,\n info=\"If true, will add a tool to the agent that returns the current date.\",\n value=True,\n ),\n ]\n outputs = [Output(name=\"response\", display_name=\"Response\", method=\"message_response\")]\n\n async def message_response(self) -> Message:\n try:\n # Get LLM model and validate\n llm_model, display_name = self.get_llm()\n if llm_model is None:\n msg = \"No language model selected. Please choose a model to proceed.\"\n raise ValueError(msg)\n self.model_name = get_model_name(llm_model, display_name=display_name)\n\n # Get memory data\n self.chat_history = await self.get_memory_data()\n\n # Add current date tool if enabled\n if self.add_current_date_tool:\n if not isinstance(self.tools, list): # type: ignore[has-type]\n self.tools = []\n current_date_tool = (await CurrentDateComponent(**self.get_base_args()).to_toolkit()).pop(0)\n if not isinstance(current_date_tool, StructuredTool):\n msg = \"CurrentDateComponent must be converted to a StructuredTool\"\n raise TypeError(msg)\n self.tools.append(current_date_tool)\n # note the tools are not required to run the agent, hence the validation removed.\n\n # Set up and run agent\n self.set(\n llm=llm_model,\n tools=self.tools or [],\n chat_history=self.chat_history,\n input_value=self.input_value,\n system_prompt=self.system_prompt,\n )\n agent = self.create_agent_runnable()\n return await self.run_agent(agent)\n\n except (ValueError, TypeError, KeyError) as e:\n logger.error(f\"{type(e).__name__}: {e!s}\")\n raise\n except ExceptionWithMessageError as e:\n logger.error(f\"ExceptionWithMessageError occurred: {e}\")\n raise\n except Exception as e:\n logger.error(f\"Unexpected error: {e!s}\")\n raise\n\n async def get_memory_data(self):\n memory_kwargs = {\n component_input.name: getattr(self, f\"{component_input.name}\") for component_input in self.memory_inputs\n }\n # filter out empty values\n memory_kwargs = {k: v for k, v in memory_kwargs.items() if v is not None}\n\n return await MemoryComponent(**self.get_base_args()).set(**memory_kwargs).retrieve_messages()\n\n def get_llm(self):\n if not isinstance(self.agent_llm, str):\n return self.agent_llm, None\n\n try:\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if not provider_info:\n msg = f\"Invalid model provider: {self.agent_llm}\"\n raise ValueError(msg)\n\n component_class = provider_info.get(\"component_class\")\n display_name = component_class.display_name\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\", \"\")\n\n return self._build_llm_model(component_class, inputs, prefix), display_name\n\n except Exception as e:\n logger.error(f\"Error building {self.agent_llm} language model: {e!s}\")\n msg = f\"Failed to initialize language model: {e!s}\"\n raise ValueError(msg) from e\n\n def _build_llm_model(self, component, inputs, prefix=\"\"):\n model_kwargs = {}\n for input_ in inputs:\n if hasattr(self, f\"{prefix}{input_.name}\"):\n model_kwargs[input_.name] = getattr(self, f\"{prefix}{input_.name}\")\n return component.set(**model_kwargs).build_model()\n\n def set_component_params(self, component):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n inputs = provider_info.get(\"inputs\")\n prefix = provider_info.get(\"prefix\")\n model_kwargs = {input_.name: getattr(self, f\"{prefix}{input_.name}\") for input_ in inputs}\n\n return component.set(**model_kwargs)\n return component\n\n def delete_fields(self, build_config: dotdict, fields: dict | list[str]) -> None:\n \"\"\"Delete specified fields from build_config.\"\"\"\n for field in fields:\n build_config.pop(field, None)\n\n def update_input_types(self, build_config: dotdict) -> dotdict:\n \"\"\"Update input types for all fields in build_config.\"\"\"\n for key, value in build_config.items():\n if isinstance(value, dict):\n if value.get(\"input_types\") is None:\n build_config[key][\"input_types\"] = []\n elif hasattr(value, \"input_types\") and value.input_types is None:\n value.input_types = []\n return build_config\n\n async def update_build_config(\n self, build_config: dotdict, field_value: str, field_name: str | None = None\n ) -> dotdict:\n # Iterate over all providers in the MODEL_PROVIDERS_DICT\n # Existing logic for updating build_config\n if field_name in (\"agent_llm\",):\n build_config[\"agent_llm\"][\"value\"] = field_value\n provider_info = MODEL_PROVIDERS_DICT.get(field_value)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call the component class's update_build_config method\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n\n provider_configs: dict[str, tuple[dict, list[dict]]] = {\n provider: (\n MODEL_PROVIDERS_DICT[provider][\"fields\"],\n [\n MODEL_PROVIDERS_DICT[other_provider][\"fields\"]\n for other_provider in MODEL_PROVIDERS_DICT\n if other_provider != provider\n ],\n )\n for provider in MODEL_PROVIDERS_DICT\n }\n if field_value in provider_configs:\n fields_to_add, fields_to_delete = provider_configs[field_value]\n\n # Delete fields from other providers\n for fields in fields_to_delete:\n self.delete_fields(build_config, fields)\n\n # Add provider-specific fields\n if field_value == \"OpenAI\" and not any(field in build_config for field in fields_to_add):\n build_config.update(fields_to_add)\n else:\n build_config.update(fields_to_add)\n # Reset input types for agent_llm\n build_config[\"agent_llm\"][\"input_types\"] = []\n elif field_value == \"Custom\":\n # Delete all provider fields\n self.delete_fields(build_config, ALL_PROVIDER_FIELDS)\n # Update with custom component\n custom_component = DropdownInput(\n name=\"agent_llm\",\n display_name=\"Language Model\",\n options=[*sorted(MODEL_PROVIDERS_DICT.keys()), \"Custom\"],\n value=\"Custom\",\n real_time_refresh=True,\n input_types=[\"LanguageModel\"],\n options_metadata=[MODELS_METADATA[key] for key in sorted(MODELS_METADATA.keys())]\n + [{\"icon\": \"brain\"}],\n )\n build_config.update({\"agent_llm\": custom_component.to_dict()})\n # Update input types for all fields\n build_config = self.update_input_types(build_config)\n\n # Validate required keys\n default_keys = [\n \"code\",\n \"_type\",\n \"agent_llm\",\n \"tools\",\n \"input_value\",\n \"add_current_date_tool\",\n \"system_prompt\",\n \"agent_description\",\n \"max_iterations\",\n \"handle_parsing_errors\",\n \"verbose\",\n ]\n missing_keys = [key for key in default_keys if key not in build_config]\n if missing_keys:\n msg = f\"Missing required keys in build_config: {missing_keys}\"\n raise ValueError(msg)\n if (\n isinstance(self.agent_llm, str)\n and self.agent_llm in MODEL_PROVIDERS_DICT\n and field_name in MODEL_DYNAMIC_UPDATE_FIELDS\n ):\n provider_info = MODEL_PROVIDERS_DICT.get(self.agent_llm)\n if provider_info:\n component_class = provider_info.get(\"component_class\")\n component_class = self.set_component_params(component_class)\n prefix = provider_info.get(\"prefix\")\n if component_class and hasattr(component_class, \"update_build_config\"):\n # Call each component class's update_build_config method\n # remove the prefix from the field_name\n if isinstance(field_name, str) and isinstance(prefix, str):\n field_name = field_name.replace(prefix, \"\")\n build_config = await update_component_build_config(\n component_class, build_config, field_value, \"model_name\"\n )\n return dotdict({k: v.to_dict() if hasattr(v, \"to_dict\") else v for k, v in build_config.items()})\n\n async def _get_tools(self) -> list[Tool]:\n component_toolkit = _get_component_toolkit()\n tools_names = self._build_tools_names()\n agent_description = self.get_tool_description()\n # TODO: Agent Description Depreciated Feature to be removed\n description = f\"{agent_description}{tools_names}\"\n tools = component_toolkit(component=self).get_tools(\n tool_name=\"Call_Agent\", tool_description=description, callbacks=self.get_langchain_callbacks()\n )\n if hasattr(self, \"tools_metadata\"):\n tools = component_toolkit(component=self, metadata=self.tools_metadata).update_tools_metadata(tools=tools)\n return tools\n" }, "handle_parsing_errors": { "_input_type": "BoolInput", @@ -1841,9 +1841,9 @@ }, "tool_mode": false }, + "selected_output": "response", "showNode": true, - "type": "Agent", - "selected_output": "response" + "type": "Agent" }, "dragging": false, "id": "Agent-0gW4Y", @@ -2019,9 +2019,9 @@ }, "tool_mode": false }, + "selected_output": "prompt", "showNode": true, - "type": "Prompt", - "selected_output": "prompt" + "type": "Prompt" }, "dragging": false, "id": "Prompt-UAMac", @@ -2612,9 +2612,9 @@ }, "tool_mode": true }, + "selected_output": "component_as_tool", "showNode": true, - "type": "YouTubeTranscripts", - "selected_output": "component_as_tool" + "type": "YouTubeTranscripts" }, "dragging": false, "id": "YouTubeTranscripts-QMIjk", @@ -2926,9 +2926,9 @@ }, "tool_mode": false }, + "selected_output": "message", "showNode": true, - "type": "ChatInput", - "selected_output": "message" + "type": "ChatInput" }, "dragging": false, "id": "ChatInput-XErsc", @@ -3273,9 +3273,9 @@ }, "tool_mode": false }, + "selected_output": "true_result", "showNode": true, - "type": "ConditionalRouter", - "selected_output": "true_result" + "type": "ConditionalRouter" }, "dragging": false, "id": "ConditionalRouter-7lzPh", @@ -3448,9 +3448,9 @@ }, "tool_mode": false }, + "selected_output": "parsed_text", "showNode": true, - "type": "parser", - "selected_output": "parsed_text" + "type": "parser" }, "dragging": false, "id": "parser-r3iNU", diff --git a/src/backend/tests/.test_durations b/src/backend/tests/.test_durations index f81827f44..06c58bcbc 100644 --- a/src/backend/tests/.test_durations +++ b/src/backend/tests/.test_durations @@ -67,272 +67,285 @@ "src/backend/tests/test_webhook.py::test_webhook_endpoint": 8.848518459000388, "src/backend/tests/test_webhook.py::test_webhook_flow_on_run_endpoint": 4.675444458000584, "src/backend/tests/test_webhook.py::test_webhook_with_random_payload": 5.161753501000476, - "src/backend/tests/unit/api/test_api_utils.py::test_get_outdated_components": 0.0018809559999226622, - "src/backend/tests/unit/api/test_api_utils.py::test_get_suggestion_message": 0.06277492900005655, - "src/backend/tests/unit/api/v1/test_api_key.py::test_create_api_key_route": 10.845413467000071, - "src/backend/tests/unit/api/v1/test_api_key.py::test_create_folder": 48.117395128, - "src/backend/tests/unit/api/v1/test_api_key.py::test_delete_api_key_route": 9.429063597000095, - "src/backend/tests/unit/api/v1/test_api_key.py::test_save_store_api_key": 18.399139549999973, - "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_combined_fields": 0.03110059599998749, - "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_logs": 0.018679720000022826, - "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_nested_structures": 0.017889905000060935, - "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_outputs": 0.023361798999985695, - "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_special_types": 0.05228774700003669, - "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_truncation": 3.282064936999973, - "src/backend/tests/unit/api/v1/test_api_schemas.py::test_vertex_build_response_serialization": 0.060049805000062406, - "src/backend/tests/unit/api/v1/test_api_schemas.py::test_vertex_build_response_with_long_data": 0.01491553399989698, - "src/backend/tests/unit/api/v1/test_endpoints.py::test_get_config": 14.125257031000046, - "src/backend/tests/unit/api/v1/test_endpoints.py::test_get_version": 14.002644186999987, - "src/backend/tests/unit/api/v1/test_endpoints.py::test_update_component_model_name_options": 9.13068379299989, - "src/backend/tests/unit/api/v1/test_endpoints.py::test_update_component_outputs": 9.440649729999905, - "src/backend/tests/unit/api/v1/test_files.py::test_delete_file": 8.555917378999993, - "src/backend/tests/unit/api/v1/test_files.py::test_download_file": 9.545656217999976, - "src/backend/tests/unit/api/v1/test_files.py::test_file_operations": 8.754432060999875, - "src/backend/tests/unit/api/v1/test_files.py::test_list_files": 8.952398174999985, - "src/backend/tests/unit/api/v1/test_files.py::test_upload_file": 9.067884420999917, - "src/backend/tests/unit/api/v1/test_files.py::test_upload_file_size_limit": 13.966648334999832, - "src/backend/tests/unit/api/v1/test_flows.py::test_create_flow": 13.446478683999999, - "src/backend/tests/unit/api/v1/test_flows.py::test_create_flows": 12.552905268000018, - "src/backend/tests/unit/api/v1/test_flows.py::test_read_basic_examples": 12.26586189999989, - "src/backend/tests/unit/api/v1/test_flows.py::test_read_flow": 12.868447253999875, - "src/backend/tests/unit/api/v1/test_flows.py::test_read_flows": 13.902817395000056, - "src/backend/tests/unit/api/v1/test_flows.py::test_update_flow": 12.272910438000054, - "src/backend/tests/unit/api/v1/test_folders.py::test_create_folder": 9.322491958000114, - "src/backend/tests/unit/api/v1/test_folders.py::test_read_folder": 9.469556184999988, - "src/backend/tests/unit/api/v1/test_folders.py::test_read_folders": 10.443600177000121, - "src/backend/tests/unit/api/v1/test_folders.py::test_update_folder": 8.610276778999946, - "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_post_endpoint_disconnect_error": 11.121664521000184, - "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_post_endpoint_invalid_json": 11.590242447000264, - "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_post_endpoint_no_auth": 12.754871386000104, - "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_post_endpoint_server_error": 11.623699202000125, - "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_post_endpoint_success": 12.466162678000387, - "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_sse_get_endpoint_invalid_auth": 12.105869954000013, - "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_sse_head_endpoint": 8.638589367999884, - "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_sse_head_endpoint_no_auth": 11.847725489000027, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_handle_project_messages_success": 11.398230424999838, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_init_mcp_servers": 9.795025958999759, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_init_mcp_servers_error_handling": 10.329510953999943, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_project_sse_creation": 10.110730528999966, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_update_project_mcp_settings_empty_settings": 8.935281497000005, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_update_project_mcp_settings_invalid_json": 21.628404242999977, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_update_project_mcp_settings_invalid_project": 12.600367326999958, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_update_project_mcp_settings_other_user_project": 21.940861649, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_update_project_mcp_settings_success": 11.360593706000145, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_user_can_only_access_own_projects": 9.094193337999968, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_user_can_update_own_flow_mcp_settings": 9.06763756999976, - "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_user_data_isolation_with_real_db": 9.153335656000081, - "src/backend/tests/unit/api/v1/test_projects.py::test_create_project": 9.096405676000131, - "src/backend/tests/unit/api/v1/test_projects.py::test_read_project": 12.306001101999982, - "src/backend/tests/unit/api/v1/test_projects.py::test_read_projects": 10.391366263000236, - "src/backend/tests/unit/api/v1/test_projects.py::test_update_project": 12.341835814999968, - "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_structure_when_truncate_applies": 0.013695154000060938, - "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_structure_without_truncate": 0.001658356999996613, - "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[0-0]": 0.001674375999982658, - "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[100-100]": 0.002577089999931559, + "src/backend/tests/unit/api/test_api_utils.py::test_get_outdated_components": 0.0009721699999545308, + "src/backend/tests/unit/api/test_api_utils.py::test_get_suggestion_message": 0.048114197000018066, + "src/backend/tests/unit/api/v1/test_api_key.py::test_create_api_key_route": 3.0329425980000337, + "src/backend/tests/unit/api/v1/test_api_key.py::test_create_folder": 6.921133701999963, + "src/backend/tests/unit/api/v1/test_api_key.py::test_delete_api_key_route": 2.325848565000001, + "src/backend/tests/unit/api/v1/test_api_key.py::test_save_store_api_key": 2.9864354929999877, + "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_combined_fields": 0.020647990000043137, + "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_logs": 0.01235756599993465, + "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_nested_structures": 0.01142391699994505, + "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_outputs": 0.01561639300001616, + "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_special_types": 1.144364435, + "src/backend/tests/unit/api/v1/test_api_schemas.py::test_result_data_response_truncation": 1.6581429129999492, + "src/backend/tests/unit/api/v1/test_api_schemas.py::test_vertex_build_response_serialization": 0.0431493599999726, + "src/backend/tests/unit/api/v1/test_api_schemas.py::test_vertex_build_response_with_long_data": 0.009558325000000423, + "src/backend/tests/unit/api/v1/test_endpoints.py::test_get_config": 1.885565199000041, + "src/backend/tests/unit/api/v1/test_endpoints.py::test_get_version": 1.822938994000026, + "src/backend/tests/unit/api/v1/test_endpoints.py::test_update_component_model_name_options": 2.287998659999971, + "src/backend/tests/unit/api/v1/test_endpoints.py::test_update_component_outputs": 2.3562188719999995, + "src/backend/tests/unit/api/v1/test_files.py::test_delete_file": 2.344283910999991, + "src/backend/tests/unit/api/v1/test_files.py::test_download_file": 2.3803300780000427, + "src/backend/tests/unit/api/v1/test_files.py::test_file_operations": 2.3504612219999785, + "src/backend/tests/unit/api/v1/test_files.py::test_list_files": 2.250169996000011, + "src/backend/tests/unit/api/v1/test_files.py::test_upload_file": 3.066032880000023, + "src/backend/tests/unit/api/v1/test_files.py::test_upload_file_size_limit": 3.149866420000137, + "src/backend/tests/unit/api/v1/test_flows.py::test_create_flow": 2.265299115000005, + "src/backend/tests/unit/api/v1/test_flows.py::test_create_flows": 2.296369528000014, + "src/backend/tests/unit/api/v1/test_flows.py::test_read_basic_examples": 3.3779587950000405, + "src/backend/tests/unit/api/v1/test_flows.py::test_read_flow": 2.367563724999968, + "src/backend/tests/unit/api/v1/test_flows.py::test_read_flows": 2.336498167000002, + "src/backend/tests/unit/api/v1/test_flows.py::test_update_flow": 2.287000457999966, + "src/backend/tests/unit/api/v1/test_folders.py::test_create_folder": 2.3529667660000086, + "src/backend/tests/unit/api/v1/test_folders.py::test_read_folder": 2.29769936699995, + "src/backend/tests/unit/api/v1/test_folders.py::test_read_folders": 2.314520322999954, + "src/backend/tests/unit/api/v1/test_folders.py::test_update_folder": 2.277791160999925, + "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_post_endpoint_disconnect_error": 2.6486981370000535, + "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_post_endpoint_invalid_json": 2.641399297000021, + "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_post_endpoint_no_auth": 2.1725163579999958, + "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_post_endpoint_server_error": 3.709548117000054, + "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_post_endpoint_success": 2.6221091189999584, + "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_sse_get_endpoint_invalid_auth": 2.14467265899998, + "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_sse_head_endpoint": 2.139444529000002, + "src/backend/tests/unit/api/v1/test_mcp.py::test_mcp_sse_head_endpoint_no_auth": 3.0788365580000345, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_handle_project_messages_success": 2.359679395999933, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_init_mcp_servers": 2.373646206999979, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_init_mcp_servers_error_handling": 2.184227509999914, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_project_sse_creation": 2.1368954610000515, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_update_project_mcp_settings_empty_settings": 2.414115416999948, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_update_project_mcp_settings_invalid_json": 2.4187000650000527, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_update_project_mcp_settings_invalid_project": 2.396014469000079, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_update_project_mcp_settings_other_user_project": 2.540346038999928, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_update_project_mcp_settings_success": 2.3150695799999994, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_user_can_only_access_own_projects": 3.7808957400000054, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_user_can_update_own_flow_mcp_settings": 2.4195308409999825, + "src/backend/tests/unit/api/v1/test_mcp_projects.py::test_user_data_isolation_with_real_db": 2.5433068720000165, + "src/backend/tests/unit/api/v1/test_projects.py::test_create_project": 2.319675876999952, + "src/backend/tests/unit/api/v1/test_projects.py::test_read_project": 2.363884212000073, + "src/backend/tests/unit/api/v1/test_projects.py::test_read_projects": 3.7230696769999554, + "src/backend/tests/unit/api/v1/test_projects.py::test_update_project": 2.3973271939999563, + "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_structure_when_truncate_applies": 0.009623100000055729, + "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_structure_without_truncate": 0.0007658050000145522, + "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[0-0]": 0.0006687349999765502, + "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[100-100]": 0.0012827390000325067, "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[1000-1000]": 0.008548625000003085, - "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[1100-101]": 0.004603191999876799, + "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[1100-101]": 0.002772633000006408, "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[2000-1001]": 0.010415454999929352, - "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[2100-101]": 0.006523155999730079, + "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[2100-101]": 0.004317118000017217, "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[3000-1001]": 0.0123209669999369, - "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[3100-101]": 0.008823069000072792, + "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[3100-101]": 0.0056621729999619674, "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[4000-1001]": 0.013948478000088471, "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[42-42]": 0.0015994080000609756, - "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[8-8]": 0.0015850490001412254, - "src/backend/tests/unit/api/v1/test_starter_projects.py::test_get_starter_projects": 13.210366947999773, - "src/backend/tests/unit/api/v1/test_store.py::test_check_if_store_is_enabled": 11.730432116999964, - "src/backend/tests/unit/api/v1/test_users.py::test_add_user": 11.146842352000021, - "src/backend/tests/unit/api/v1/test_users.py::test_delete_user": 8.752214350000031, - "src/backend/tests/unit/api/v1/test_users.py::test_patch_user": 9.136495977999857, - "src/backend/tests/unit/api/v1/test_users.py::test_read_all_users": 12.325971165000055, - "src/backend/tests/unit/api/v1/test_users.py::test_read_current_user": 9.460862033000012, - "src/backend/tests/unit/api/v1/test_users.py::test_reset_password": 9.234861616999751, - "src/backend/tests/unit/api/v1/test_validate.py::test_post_validate_code": 9.369447074999698, - "src/backend/tests/unit/api/v1/test_validate.py::test_post_validate_code_with_unauthenticated_user": 8.357954857999857, - "src/backend/tests/unit/api/v1/test_validate.py::test_post_validate_prompt": 8.874277483999776, - "src/backend/tests/unit/api/v1/test_validate.py::test_post_validate_prompt_with_invalid_data": 8.56645635200016, - "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable": 8.709243733000221, + "src/backend/tests/unit/api/v1/test_schemas.py::test_vertex_response_truncation_behavior[8-8]": 0.0007204310000474834, + "src/backend/tests/unit/api/v1/test_starter_projects.py::test_get_starter_projects": 2.6296939929999894, + "src/backend/tests/unit/api/v1/test_store.py::test_check_if_store_is_enabled": 1.8892367010000726, + "src/backend/tests/unit/api/v1/test_users.py::test_add_user": 2.1325980639999784, + "src/backend/tests/unit/api/v1/test_users.py::test_delete_user": 2.5311590160000037, + "src/backend/tests/unit/api/v1/test_users.py::test_patch_user": 4.163598618000037, + "src/backend/tests/unit/api/v1/test_users.py::test_read_all_users": 2.33847249899992, + "src/backend/tests/unit/api/v1/test_users.py::test_read_current_user": 2.3482971669999984, + "src/backend/tests/unit/api/v1/test_users.py::test_reset_password": 2.8655556249999563, + "src/backend/tests/unit/api/v1/test_validate.py::test_post_validate_code": 2.425210046000018, + "src/backend/tests/unit/api/v1/test_validate.py::test_post_validate_code_with_unauthenticated_user": 1.922201924000035, + "src/backend/tests/unit/api/v1/test_validate.py::test_post_validate_prompt": 2.4173042909999936, + "src/backend/tests/unit/api/v1/test_validate.py::test_post_validate_prompt_with_invalid_data": 2.368873576999988, + "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable": 2.4053787359999887, "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__Exception": 5.891528583015315, "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__HTTPException": 2.8841335409670137, - "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__exception": 9.165770736000013, - "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__httpexception": 8.840330464999852, + "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__exception": 2.3669266729999663, + "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__httpexception": 2.431461612000021, "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__variable_name_alread_exists": 3.690157334029209, - "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__variable_name_already_exists": 10.26783337300003, - "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__variable_name_and_value_cannot_be_empty": 8.515965370000004, - "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__variable_name_cannot_be_empty": 8.623157542999934, - "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__variable_value_cannot_be_empty": 8.707013120999818, - "src/backend/tests/unit/api/v1/test_variable.py::test_delete_variable": 8.478442478999796, + "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__variable_name_already_exists": 2.433346770000014, + "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__variable_name_and_value_cannot_be_empty": 4.008466090999946, + "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__variable_name_cannot_be_empty": 2.4373304959999587, + "src/backend/tests/unit/api/v1/test_variable.py::test_create_variable__variable_value_cannot_be_empty": 2.373667714000021, + "src/backend/tests/unit/api/v1/test_variable.py::test_delete_variable": 4.281813418000013, "src/backend/tests/unit/api/v1/test_variable.py::test_delete_variable__Exception": 3.1565893749939278, - "src/backend/tests/unit/api/v1/test_variable.py::test_delete_variable__exception": 8.47668799500002, - "src/backend/tests/unit/api/v1/test_variable.py::test_read_variables": 9.175956391000227, - "src/backend/tests/unit/api/v1/test_variable.py::test_read_variables__": 8.489244426000141, - "src/backend/tests/unit/api/v1/test_variable.py::test_read_variables__empty": 9.443553118999716, - "src/backend/tests/unit/api/v1/test_variable.py::test_update_variable": 8.500905911000018, + "src/backend/tests/unit/api/v1/test_variable.py::test_delete_variable__exception": 2.3800334079999175, + "src/backend/tests/unit/api/v1/test_variable.py::test_read_variables": 2.3537375960000304, + "src/backend/tests/unit/api/v1/test_variable.py::test_read_variables__": 2.397795181000049, + "src/backend/tests/unit/api/v1/test_variable.py::test_read_variables__empty": 2.502006160999997, + "src/backend/tests/unit/api/v1/test_variable.py::test_update_variable": 2.4127556910000294, "src/backend/tests/unit/api/v1/test_variable.py::test_update_variable__Exception": 3.202228542009834, - "src/backend/tests/unit/api/v1/test_variable.py::test_update_variable__exception": 10.148777363999898, - "src/backend/tests/unit/api/v2/test_files.py::test_delete_file": 8.473131878999993, - "src/backend/tests/unit/api/v2/test_files.py::test_download_file": 8.66909816700013, - "src/backend/tests/unit/api/v2/test_files.py::test_edit_file": 8.450433602999965, - "src/backend/tests/unit/api/v2/test_files.py::test_list_files": 8.62978036100003, - "src/backend/tests/unit/api/v2/test_files.py::test_upload_file": 9.781430844999932, - "src/backend/tests/unit/base/load/test_load.py::test_run_flow_from_json_params": 0.001833072999943397, - "src/backend/tests/unit/base/load/test_load.py::test_run_flow_with_fake_env": 0.0826570240003548, - "src/backend/tests/unit/base/load/test_load.py::test_run_flow_with_fake_env_tweaks": 0.06813695600021674, + "src/backend/tests/unit/api/v1/test_variable.py::test_update_variable__exception": 2.3629998409999757, + "src/backend/tests/unit/api/v2/test_files.py::test_delete_file": 2.4711873019999757, + "src/backend/tests/unit/api/v2/test_files.py::test_download_file": 2.386917947000029, + "src/backend/tests/unit/api/v2/test_files.py::test_edit_file": 2.417282548000003, + "src/backend/tests/unit/api/v2/test_files.py::test_list_files": 2.367332523000073, + "src/backend/tests/unit/api/v2/test_files.py::test_upload_file": 2.356027483999924, + "src/backend/tests/unit/base/load/test_load.py::test_run_flow_from_json_params": 0.0009234189999460796, + "src/backend/tests/unit/base/load/test_load.py::test_run_flow_with_fake_env": 0.021331329999952686, + "src/backend/tests/unit/base/load/test_load.py::test_run_flow_with_fake_env_tweaks": 0.015597353000089242, "src/backend/tests/unit/base/models/test_model_constants.py::test_provider_names": 0.024663168034749106, "src/backend/tests/unit/base/tools/test_component_tool.py::test_component_tool": 0.04467487393412739, - "src/backend/tests/unit/base/tools/test_component_toolkit.py::test_component_tool": 0.00439214399989396, - "src/backend/tests/unit/base/tools/test_component_toolkit.py::test_component_tool_with_api_key": 8.00260180100031, - "src/backend/tests/unit/base/tools/test_create_schema.py::test_create_schema": 0.002069155000071987, - "src/backend/tests/unit/base/tools/test_toolmodemixin.py::test_component_inputs_toolkit": 0.007691725999848131, - "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_all_versions_have_a_file_name_defined": 0.0014372740001817874, - "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_component_versions[1.0.19]": 0.0014063460000670602, - "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_component_versions[1.1.0]": 0.0014142520001314551, - "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_component_versions[1.1.1]": 0.0013825910000377917, - "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_decorator_applied": 0.0041630260000147246, - "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_latest_version": 0.016465680999772303, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_all_versions_have_a_file_name_defined": 0.001493399000082718, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_build_config_update": 0.02283127999999124, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_component_versions[1.0.19]": 0.001484863000086989, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_component_versions[1.1.0]": 0.0015188670001862192, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_component_versions[1.1.1]": 0.0019340230001034797, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_latest_version": 0.008442086000059135, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_agent_component_with_all_openai_models": 8.088072428999794, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_agent_component_with_calculator": 8.160676852000051, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_all_versions_have_a_file_name_defined": 10.087212797999882, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_component_versions[1.0.19]": 8.009093388999872, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_component_versions[1.1.0]": 8.081434230000013, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_component_versions[1.1.1]": 7.991517521999867, - "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_latest_version": 8.005226579000237, + "src/backend/tests/unit/base/tools/test_component_toolkit.py::test_component_tool": 0.0024859680000872686, + "src/backend/tests/unit/base/tools/test_component_toolkit.py::test_component_tool_with_api_key": 3.2598204649999616, + "src/backend/tests/unit/base/tools/test_component_toolkit.py::test_sql_component_to_toolkit": 4.583409683000127, + "src/backend/tests/unit/base/tools/test_create_schema.py::test_create_schema": 0.0010414289999971515, + "src/backend/tests/unit/base/tools/test_toolmodemixin.py::test_component_inputs_toolkit": 0.004227562999858492, + "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_all_versions_have_a_file_name_defined": 0.0006289709999691695, + "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_component_versions[1.0.19]": 0.0006346330000042144, + "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_component_versions[1.1.0]": 0.0006441489999815531, + "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_component_versions[1.1.1]": 0.0006027619999713352, + "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_decorator_applied": 0.0011645379998981298, + "src/backend/tests/unit/base/tools/test_vector_store_decorator.py::TestVectorStoreDecorator::test_latest_version": 0.009159410000165735, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_all_versions_have_a_file_name_defined": 0.0007252999999991516, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_build_config_update": 0.016895613000087906, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_component_versions[1.0.19]": 0.0006922990002067309, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_component_versions[1.1.0]": 0.0006690050001907366, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_component_versions[1.1.1]": 0.0006709680000085427, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponent::test_latest_version": 0.006307337000066582, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_agent_component_with_all_anthropic_models": 1.9996748710001384, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_agent_component_with_all_openai_models": 35.46384977900004, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_agent_component_with_calculator": 3.943867705999878, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_all_versions_have_a_file_name_defined": 1.9922647669998241, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_component_versions[1.0.19]": 3.866181934999986, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_component_versions[1.1.0]": 1.9846810130001131, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_component_versions[1.1.1]": 2.0040248730000485, + "src/backend/tests/unit/components/agents/test_agent_component.py::TestAgentComponentWithClient::test_latest_version": 1.989620804000083, "src/backend/tests/unit/components/agents/test_agent_component.py::test_agent_component_with_calculator": 9.962897010000006, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_chain_end_event": 0.0027929559998938203, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_chain_start_event": 0.0031412369999088696, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_chain_stream_event": 0.002551557000288085, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_end_empty_data": 0.0017983989998811012, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_end_no_output": 0.0018524709998928302, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_end_with_empty_return_values": 0.0018114229999355302, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_end_with_output": 0.0018646720000106143, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_start_no_input": 0.0018256099999689468, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_start_with_input": 0.0018954899996970198, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_stream_no_output": 0.002480040999898847, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_stream_with_output": 0.0018236659998365212, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_tool_end": 0.001830198000106975, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_tool_error": 0.0018959719998292712, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_tool_start": 0.0018257799997627444, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_multiple_events": 0.0029801460002545355, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_tool_end_event": 0.0027989580000848946, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_tool_error_event": 0.002783077999993111, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_tool_start_event": 0.0030231760001697694, - "src/backend/tests/unit/components/agents/test_agent_events.py::test_unknown_event": 0.003301116000102411, - "src/backend/tests/unit/components/agents/test_tool_calling_agent.py::test_tool_calling_agent_component": 9.795589277999852, - "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_all_versions_have_a_file_name_defined": 0.0015895880001153273, - "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_build_action_maps": 0.0020050640000590647, - "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_build_wrapper_no_api_key": 0.003123333000303319, - "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_build_wrapper_with_api_key": 0.0021664869998403447, - "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_component_versions[1.0.19]": 0.0016700900000614638, - "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_component_versions[1.1.0]": 0.001603003999662178, - "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_component_versions[1.1.1]": 0.0016522660000646283, - "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_get_action_fields": 0.0019969510001374147, - "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_latest_version": 0.005534687999897869, - "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_show_hide_fields": 0.0020145330001923867, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_all_versions_have_a_file_name_defined": 0.0015325530000609433, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_as_dataframe": 0.011333960000001753, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_component_versions[1.0.19]": 0.0015850709999085666, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_component_versions[1.1.0]": 0.001591703000030975, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_component_versions[1.1.1]": 0.001783171999932165, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_execute_action_invalid_action": 0.00344716800009337, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_execute_action_list_branches": 0.003258036000033826, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_execute_action_list_repo_issues": 0.0034849790001771908, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_execute_action_star_a_repo": 0.0032713609998609172, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_init": 0.003574797999817747, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_latest_version": 0.009484585999871342, - "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_update_build_config": 0.0041483080001398775, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_all_versions_have_a_file_name_defined": 0.0014697859999159846, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_as_dataframe": 0.009719835999931092, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_component_versions[1.0.19]": 0.0015362179999556247, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_component_versions[1.1.0]": 0.0015112220000901289, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_component_versions[1.1.1]": 0.0014839919999758422, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_execute_action_fetch_emails": 0.0028278509996653156, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_execute_action_get_profile": 0.0025909399998909066, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_execute_action_invalid_action": 0.0026686749997679726, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_execute_action_send_email": 0.002584877999879609, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_init": 0.0028799690001051204, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_latest_version": 0.007840554000040356, - "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_update_build_config": 0.004828376999739703, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_all_versions_have_a_file_name_defined": 0.0014526229997500195, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_as_dataframe": 0.008179108000149427, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_component_versions[1.0.19]": 0.0014928680000139138, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_component_versions[1.1.0]": 0.0015145089998895855, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_component_versions[1.1.1]": 0.0015044099998249294, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_execute_action_create_event": 0.003555281999979343, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_execute_action_invalid_action": 0.003519263999805844, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_execute_action_list_calendars": 0.003739134999932503, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_init": 0.003783357000202159, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_latest_version": 0.010506234000104087, - "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_update_build_config": 0.004119924999940849, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_all_versions_have_a_file_name_defined": 0.0014476430001195695, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_as_dataframe": 0.00779742399981842, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_component_versions[1.0.19]": 0.0014942010000140726, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_component_versions[1.1.0]": 0.0014418839998597832, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_component_versions[1.1.1]": 0.0015019960001154686, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_execute_action_invalid_action": 0.003224533000320662, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_execute_action_list_all_slack_team_users": 0.003353191999849514, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_execute_action_send_message_to_channel": 0.0031182739999167097, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_init": 0.0033658059999197576, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_latest_version": 0.009087703999966834, - "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_update_build_config": 0.0038104569996448845, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_all_versions_have_a_file_name_defined": 0.0019617650002601295, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_complex_query_result": 0.010153876999765998, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_component_versions[1.0.19]": 0.0019568650002383947, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_component_versions[1.1.0]": 0.001996859000200857, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_component_versions[1.1.1]": 0.002010475999895789, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_empty_query_raises[ \\n\\t ]": 0.005572498000219639, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_empty_query_raises[]": 0.005317441999977746, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_execute_sql_invalid_query": 0.004697265000004336, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_execute_sql_success": 0.00702136499990047, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_invalid_service_account_json": 0.005406099000083486, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_latest_version": 0.007594886999868322, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_missing_project_id_in_credentials": 0.0038842939998176007, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_missing_service_account_file": 0.0037557440000455244, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_multiple_statements": 0.006749105999915628, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_parameters": 0.006798588000037853, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_quotes": 0.022814273999983925, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_special_characters": 0.008191169999918202, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_sql_code_block": 0.005498601000226699, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_whitespace": 0.006910637999908431, - "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_refresh_error_handling": 0.004351176000227497, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_all_versions_have_a_file_name_defined": 0.0014217569996617385, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_basic_setup": 0.0033558579998498317, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_component_versions[1.0.19]": 0.0013798269997096213, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_component_versions[1.1.0]": 0.001417237000168825, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_component_versions[1.1.1]": 0.0017940009997801099, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_empty_transcript_handling": 0.00463019699986944, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_get_data_output_success": 0.004268332000037844, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_get_dataframe_output_success": 0.004674471000043923, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_get_message_output_success": 0.004046879000043191, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_latest_version": 0.007348163999949975, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_no_transcript_found_error": 0.0038278290001017012, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_transcript_disabled_error": 0.0045665589998407086, - "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_translation_setting": 0.0033658970000942645, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_add_query_params": 0.0036658169999554957, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_all_versions_have_a_file_name_defined": 0.001417516999936197, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_component_versions[1.0.19]": 0.0014125479999620438, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_component_versions[1.1.0]": 0.0014875079998546425, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_component_versions[1.1.1]": 0.0018283149997841974, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_error_handling": 0.05207526699996379, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_invalid_urls": 0.004307866000090144, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_latest_version": 0.009177941999951145, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_api_request": 0.03577396100013175, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_binary_response": 0.028170206999902803, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_save_to_file": 0.030807471000116493, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_success": 0.028941886999973576, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_timeout": 0.027655736000042452, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_with_metadata": 0.028210223000087353, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_with_redirects": 0.02957460000015999, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_chain_end_event": 0.0014733599998635327, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_chain_start_event": 0.0017574689999264592, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_chain_stream_event": 0.0013055280001026404, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_end_empty_data": 0.0016503080000802584, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_end_no_output": 0.0008815689999437382, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_end_with_empty_return_values": 0.0009433730000409923, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_end_with_output": 0.0009402389999877414, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_start_no_input": 0.000905474999967737, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_start_with_input": 0.0009268639998936123, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_stream_no_output": 0.0009114340000451193, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_chain_stream_with_output": 0.0009443469999723675, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_tool_end": 0.0009868739999774334, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_tool_error": 0.0009583620000057635, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_handle_on_tool_start": 0.0009691619999330214, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_multiple_events": 0.0016207529999974213, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_tool_end_event": 0.0014888090000795273, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_tool_error_event": 0.0014459190000479794, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_tool_start_event": 0.001630232000138676, + "src/backend/tests/unit/components/agents/test_agent_events.py::test_unknown_event": 0.0013145839999424425, + "src/backend/tests/unit/components/agents/test_tool_calling_agent.py::test_tool_calling_agent_component": 3.4139768160000585, + "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_all_versions_have_a_file_name_defined": 0.0007329240000899517, + "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_build_action_maps": 0.0008231130000240228, + "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_build_wrapper_no_api_key": 0.0009380369998552851, + "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_build_wrapper_with_api_key": 0.0009155239998790421, + "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_component_versions[1.0.19]": 0.0007407690000036382, + "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_component_versions[1.1.0]": 0.0007063550000339092, + "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_component_versions[1.1.1]": 0.0007154229998604933, + "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_get_action_fields": 0.000789379000025292, + "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_latest_version": 0.0031020670000998507, + "src/backend/tests/unit/components/bundles/composio/test_base.py::TestComposioBase::test_show_hide_fields": 0.0008060620000378549, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_all_versions_have_a_file_name_defined": 0.000653267000075175, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_as_dataframe": 0.007761330999983329, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_component_versions[1.0.19]": 0.0007053530000575847, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_component_versions[1.1.0]": 0.0006678630001033525, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_component_versions[1.1.1]": 0.0006554109999115099, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_execute_action_invalid_action": 0.001771397999959845, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_execute_action_list_branches": 0.003357641999969019, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_execute_action_list_repo_issues": 0.0017052650001687653, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_execute_action_star_a_repo": 0.0016887150000002293, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_init": 0.0015521499999522348, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_latest_version": 0.005908542000042871, + "src/backend/tests/unit/components/bundles/composio/test_github.py::TestGitHubComponent::test_update_build_config": 0.002045368000040071, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_all_versions_have_a_file_name_defined": 0.0006846150000683338, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_as_dataframe": 0.006663187000071957, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_component_versions[1.0.19]": 0.0006841450000365512, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_component_versions[1.1.0]": 0.0006887619999815797, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_component_versions[1.1.1]": 0.0006734639998740022, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_execute_action_fetch_emails": 0.0018063220001067748, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_execute_action_get_profile": 0.0012477550000085103, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_execute_action_invalid_action": 0.0012723390000246582, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_execute_action_send_email": 0.0012540859999035092, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_init": 0.001163586999950894, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_latest_version": 0.004715690000125505, + "src/backend/tests/unit/components/bundles/composio/test_gmail.py::TestGmailComponent::test_update_build_config": 0.0016472570000587439, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_all_versions_have_a_file_name_defined": 0.0006832520000443765, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_as_dataframe": 0.005455178000147498, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_component_versions[1.0.19]": 0.0006894240000292484, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_component_versions[1.1.0]": 0.000686466999923141, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_component_versions[1.1.1]": 0.0006715510000958602, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_execute_action_create_event": 0.0018944189999956507, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_execute_action_invalid_action": 0.0018784070000492648, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_execute_action_list_calendars": 0.002022665999788842, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_init": 0.002085842999917986, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_latest_version": 0.006555676000061794, + "src/backend/tests/unit/components/bundles/composio/test_googlecalendar.py::TestGoogleCalendarComponent::test_update_build_config": 0.0021981940001296607, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_all_versions_have_a_file_name_defined": 0.000675077999972018, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_as_dataframe": 0.0034768240000175865, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_component_versions[1.0.19]": 0.0006960460001437241, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_component_versions[1.1.0]": 0.000688371999899573, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_component_versions[1.1.1]": 0.0006825400000707305, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_execute_action_fetch_emails": 0.001962182999932338, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_execute_action_invalid_action": 0.001820651999992151, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_execute_action_send_email": 0.0017923179999570493, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_init": 0.00202869700001429, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_latest_version": 0.006585160999975415, + "src/backend/tests/unit/components/bundles/composio/test_outlook.py::TestOutlookComponent::test_update_build_config": 0.0021629679999932705, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_all_versions_have_a_file_name_defined": 0.0006522150000591864, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_as_dataframe": 0.005111768000006123, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_component_versions[1.0.19]": 0.000683322999975644, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_component_versions[1.1.0]": 0.000690615999928923, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_component_versions[1.1.1]": 0.0006695379998973294, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_execute_action_invalid_action": 0.001629063999985192, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_execute_action_list_all_slack_team_users": 0.0018068450000328085, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_execute_action_send_message_to_channel": 0.0016120029999910912, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_init": 0.0018453679999765882, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_latest_version": 0.0051924180000924025, + "src/backend/tests/unit/components/bundles/composio/test_slack.py::TestSlackComponent::test_update_build_config": 0.001968736999970133, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_all_versions_have_a_file_name_defined": 0.0010569680001708548, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_complex_query_result": 0.004368032000002131, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_component_versions[1.0.19]": 0.001055625999924814, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_component_versions[1.1.0]": 0.0010633199999574572, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_component_versions[1.1.1]": 0.0010198879998597477, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_empty_query_raises[ \\n\\t ]": 0.0024088359999723252, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_empty_query_raises[]": 0.002761594000048717, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_execute_sql_invalid_query": 0.002217127999870172, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_execute_sql_success": 0.003566672000033577, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_invalid_service_account_json": 0.0026221429998258827, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_latest_version": 0.0037573050000219155, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_missing_project_id_in_credentials": 0.0015192399999932604, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_missing_service_account_file": 0.0013805100001036408, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_multiple_statements": 0.0035658199999488716, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_parameters": 0.004855332000033741, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_quotes": 0.0078602259999343, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_special_characters": 0.003640989000018635, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_sql_code_block": 0.0026643619999049406, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_query_with_whitespace": 0.003698036000059801, + "src/backend/tests/unit/components/bundles/google/test_google_bq_sql_executor_component.py::TestBigQueryExecutorComponent::test_refresh_error_handling": 0.0017895799999223527, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_all_versions_have_a_file_name_defined": 0.0006271180001249377, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_basic_setup": 0.0008361170000625862, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_component_versions[1.0.19]": 0.0009278479999466072, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_component_versions[1.1.0]": 0.0005967199998622164, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_component_versions[1.1.1]": 0.0006264259999397837, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_empty_transcript_handling": 0.0015916639998749815, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_get_data_output_success": 0.0012685229999078729, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_get_dataframe_output_success": 0.001780614999915997, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_get_message_output_success": 0.0013730979999309056, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_latest_version": 0.0030959349999193364, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_no_transcript_found_error": 0.0012440460000107123, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_transcript_disabled_error": 0.0020771279999962644, + "src/backend/tests/unit/components/bundles/youtube/test_youtube_transcript_component.py::TestYouTubeTranscriptsComponent::test_translation_setting": 0.0008584589999145464, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_add_query_params": 0.0013609050001832657, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_all_versions_have_a_file_name_defined": 0.0006157269999675918, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_component_versions[1.0.19]": 0.0006415549999019277, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_component_versions[1.1.0]": 0.0006187420000287602, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_component_versions[1.1.1]": 0.0005989249999629465, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_error_handling": 0.040291724999974576, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_invalid_urls": 0.0016435009999895556, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_latest_version": 0.005404353000017181, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_api_request": 0.026713120999943385, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_binary_response": 0.02191893400004119, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_save_to_file": 0.023377300000106516, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_success": 0.022942679999914617, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_timeout": 0.021370423000121264, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_with_metadata": 0.021869472000048518, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_make_request_with_redirects": 0.022577488999900197, "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_output_formats": 0.005004472999871723, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_parse_curl": 0.0037322910000057163, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_process_body": 0.0036922369997682836, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_process_headers": 0.003688299000259576, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_response_info": 0.005784113999879992, - "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_update_build_config": 0.0038138629997774842, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_parse_curl": 0.0014449800000875257, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_process_body": 0.0013255390001631895, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_process_headers": 0.0013330820000874155, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_response_info": 0.0024522160000515214, + "src/backend/tests/unit/components/data/test_api_request_component.py::TestAPIRequestComponent::test_update_build_config": 0.0014010980000875861, "src/backend/tests/unit/components/data/test_api_request_component.py::test_httpx_metadata_behavior[False-expected_properties0]": 0.02888980000011543, "src/backend/tests/unit/components/data/test_api_request_component.py::test_httpx_metadata_behavior[True-expected_properties1]": 0.028863217999855806, "src/backend/tests/unit/components/data/test_api_request_component.py::test_parse_curl": 0.003312925000159339, @@ -342,60 +355,69 @@ "src/backend/tests/unit/components/data/test_api_request_component.py::test_response_info_non_binary_content": 0.003093106999926931, "src/backend/tests/unit/components/data/test_api_request_component.py::test_save_to_file_behavior[False-expected_properties0]": 0.028578312000149708, "src/backend/tests/unit/components/data/test_api_request_component.py::test_save_to_file_behavior[True-expected_properties1]": 0.0307529940000677, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_all_versions_have_a_file_name_defined": 0.0019452240001101018, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_component_versions[1.0.19]": 0.03786378300014803, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_component_versions[1.1.0]": 0.03429177099997105, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_component_versions[1.1.1]": 0.036212858999988384, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_as_dataframe": 0.005884890999823256, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_component_build_with_multithreading": 0.004718614000012167, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_invalid_type": 0.003767518000131531, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_depth": 0.005066903999704664, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_hidden_files": 0.004372767999939242, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_multithreading": 0.004578692000222873, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_types[file_types0-1]": 0.004176770999720247, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_types[file_types1-1]": 0.004189314000313971, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_types[file_types2-2]": 0.004239578000124311, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_without_mocks": 0.09454095499972937, - "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_latest_version": 0.006992962000140324, - "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_all_versions_have_a_file_name_defined": 0.0014418940002087766, - "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_component_versions[1.0.19]": 0.0014171159998568328, - "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_component_versions[1.1.0]": 0.0014125879999937752, - "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_component_versions[1.1.1]": 0.0013926010001341638, - "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_empty_news_results": 0.005619276000061291, - "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_latest_version": 0.008371637000209375, - "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_news_search_error": 0.004885755000032077, - "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_successful_news_search": 0.006952295000019149, - "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_all_versions_have_a_file_name_defined": 0.0014650359998995555, - "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_component_versions[1.0.19]": 0.0014908739997281373, - "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_component_versions[1.1.0]": 0.0014524320001783053, - "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_component_versions[1.1.1]": 0.0014151530001527135, - "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_empty_rss_feed": 0.004415426000150546, - "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_latest_version": 0.0059505949998310825, - "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_rss_fetch_error": 0.0036900130000958598, - "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_rss_fetch_with_missing_fields": 0.004582047999974748, - "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_successful_rss_fetch": 0.0054729930000121385, - "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_all_versions_have_a_file_name_defined": 0.00027193699997951626, - "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_component_versions[1.0.19]": 0.00028683499999715423, - "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_component_versions[1.1.0]": 0.00026193999997303763, - "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_component_versions[1.1.1]": 0.0002595259998088295, - "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_latest_version": 0.00028981100012970273, - "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_upload": 0.00025655800004642515, - "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_all_versions_have_a_file_name_defined": 0.0041254929999468, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_all_versions_have_a_file_name_defined": 0.0009340990000055172, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_component_versions[1.0.19]": 0.029640982999922016, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_component_versions[1.1.0]": 0.02472969699999794, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_component_versions[1.1.1]": 0.025592104999986987, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_as_dataframe": 0.0026770760001681992, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_component_build_with_multithreading": 0.002033846000131234, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_invalid_type": 0.0015324029999419508, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_depth": 0.0023309010000502894, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_hidden_files": 0.0019430670000701866, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_multithreading": 0.0018536620001441406, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_types[file_types0-1]": 0.0018519989998821984, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_types[file_types1-1]": 0.0018631299999469775, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_with_types[file_types2-2]": 0.001903264999896237, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_directory_without_mocks": 0.0805575699999963, + "src/backend/tests/unit/components/data/test_directory_component.py::TestDirectoryComponent::test_latest_version": 0.003112977000000683, + "src/backend/tests/unit/components/data/test_mcp_component.py::TestMCPSseClient::test_connect_timeout": 0.0001788629999737168, + "src/backend/tests/unit/components/data/test_mcp_component.py::TestMCPSseClient::test_connect_to_server": 0.00017680899986771692, + "src/backend/tests/unit/components/data/test_mcp_component.py::TestMCPSseClient::test_pre_check_redirect": 0.0001835010000377224, + "src/backend/tests/unit/components/data/test_mcp_component.py::TestMCPStdioClient::test_connect_to_server": 0.00019868000003953057, + "src/backend/tests/unit/components/data/test_mcp_component.py::TestMCPToolsComponent::test_all_versions_have_a_file_name_defined": 0.00019000399993274186, + "src/backend/tests/unit/components/data/test_mcp_component.py::TestMCPToolsComponent::test_component_versions[1.0.19]": 0.00018189800005075085, + "src/backend/tests/unit/components/data/test_mcp_component.py::TestMCPToolsComponent::test_component_versions[1.1.0]": 0.0002090389999693798, + "src/backend/tests/unit/components/data/test_mcp_component.py::TestMCPToolsComponent::test_component_versions[1.1.1]": 0.00017885299996578397, + "src/backend/tests/unit/components/data/test_mcp_component.py::TestMCPToolsComponent::test_latest_version": 0.00021735499990427343, + "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_all_versions_have_a_file_name_defined": 0.0006330500000331085, + "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_component_versions[1.0.19]": 0.0006390419999888763, + "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_component_versions[1.1.0]": 0.0006178590000445183, + "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_component_versions[1.1.1]": 0.0006141430000070613, + "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_empty_news_results": 0.0017042140001422013, + "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_latest_version": 0.003897617999882641, + "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_news_search_error": 0.0014376079999465219, + "src/backend/tests/unit/components/data/test_news_search.py::TestNewsSearchComponent::test_successful_news_search": 0.002492331000098602, + "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_all_versions_have_a_file_name_defined": 0.0006332400000701455, + "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_component_versions[1.0.19]": 0.0006431780000184517, + "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_component_versions[1.1.0]": 0.001049362999992809, + "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_component_versions[1.1.1]": 0.0006034340000269367, + "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_empty_rss_feed": 0.002003511999987495, + "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_latest_version": 0.0025537749999102743, + "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_rss_fetch_error": 0.001431555999943157, + "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_rss_fetch_with_missing_fields": 0.002006005999987792, + "src/backend/tests/unit/components/data/test_rss.py::TestRSSReaderComponent::test_successful_rss_fetch": 0.002179848999958267, + "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_all_versions_have_a_file_name_defined": 0.00018122799997399852, + "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_component_versions[1.0.19]": 0.00018409299991617445, + "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_component_versions[1.1.0]": 0.0001798849999659069, + "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_component_versions[1.1.1]": 0.00018844999999600986, + "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_latest_version": 0.00021131400012563972, + "src/backend/tests/unit/components/data/test_s3_uploader_component.py::TestS3UploaderComponent::test_upload": 0.0001952629999095734, + "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_all_versions_have_a_file_name_defined": 0.0030424660000107906, "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_build_data": 0.005873824999525823, "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_build_dataframe": 0.00853606999976364, - "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_component_versions[1.0.19]": 0.003860170000052676, - "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_component_versions[1.1.0]": 0.004695028999776696, - "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_component_versions[1.1.1]": 0.003947776999893904, - "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_latest_version": 0.016694472999915888, - "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_query_error_with_add_error": 0.005344161999573771, - "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_run_sql_query": 0.005488810999850102, - "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_successful_query_with_columns": 0.010181669000075999, - "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_successful_query_without_columns": 0.005049040999892895, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_all_versions_have_a_file_name_defined": 0.0014001450001615012, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_component_versions[1.0.19]": 0.24676510400013285, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_component_versions[1.1.0]": 0.22410144799982845, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_component_versions[1.1.1]": 0.2266192349998164, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_latest_version": 0.006650030999935552, + "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_component_versions[1.0.19]": 0.003110061000029418, + "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_component_versions[1.1.0]": 0.002987031999850842, + "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_component_versions[1.1.1]": 0.002942587999882562, + "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_latest_version": 0.00924343899998803, + "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_query_error_with_add_error": 0.005002906999948209, + "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_run_sql_query": 0.005427445999998781, + "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_successful_query_with_columns": 0.008069284999919546, + "src/backend/tests/unit/components/data/test_sql_executor.py::TestSQLComponent::test_successful_query_without_columns": 0.004720990000009806, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_all_versions_have_a_file_name_defined": 0.0006696960000454055, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_component_versions[1.0.19]": 0.2278344820000484, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_component_versions[1.1.0]": 0.21163755200007017, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_component_versions[1.1.1]": 0.20893100299997514, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_latest_version": 0.0038033330001780996, "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_recursive_url_component": 0.0042570200000682235, "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_recursive_url_component_as_dataframe": 0.004986199000086344, "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_recursive_url_component_ensure_url": 0.003239873000211446, @@ -405,22 +427,22 @@ "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_recursive_url_component_multiple_urls": 0.004476819999808868, "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component": 0.0032953139999563064, "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_as_dataframe": 0.00391441199997189, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_basic_functionality": 0.004231543999821952, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_ensure_url": 0.003019110000195724, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_error_handling": 0.0030747540001812013, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_basic_functionality": 0.002480795999986185, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_ensure_url": 0.0009936229999993884, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_error_handling": 0.0014929940000456554, "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_fetch_content_text": 0.0030438270000558987, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_format_options": 0.004401871000027313, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_format_options": 0.0024768789999143337, "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_invalid_urls": 0.0025321470000108093, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_missing_metadata": 0.0035502709997672355, - "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_multiple_urls": 0.0037211200001365796, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_missing_metadata": 0.0018417340000951299, + "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_component_multiple_urls": 0.0024929390000352214, "src/backend/tests/unit/components/data/test_url_component.py::TestURLComponent::test_url_request_success": 0.00575876200014136, - "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_all_versions_have_a_file_name_defined": 0.0014419330002510833, - "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_component_versions[1.0.19]": 0.0014126490000307967, - "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_component_versions[1.1.0]": 0.001428537999800028, - "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_component_versions[1.1.1]": 0.001407818999950905, - "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_invalid_url_handling": 0.004345977999946626, - "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_latest_version": 0.00706781099984255, - "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_successful_web_search": 2.523861979000003, + "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_all_versions_have_a_file_name_defined": 0.0006196349999072481, + "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_component_versions[1.0.19]": 0.0006005799999684314, + "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_component_versions[1.1.0]": 0.0005889469999829089, + "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_component_versions[1.1.1]": 0.0005986160001612006, + "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_invalid_url_handling": 0.000995035999949323, + "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_latest_version": 0.0029461430001447297, + "src/backend/tests/unit/components/data/test_web_search.py::TestWebSearchComponent::test_successful_web_search": 5.414084098000103, "src/backend/tests/unit/components/embeddings/test_embedding_model_component.py::TestEmbeddingModelComponent::test_all_versions_have_a_file_name_defined": 8.159916476000035, "src/backend/tests/unit/components/embeddings/test_embedding_model_component.py::TestEmbeddingModelComponent::test_build_embeddings_openai": 10.576514679999946, "src/backend/tests/unit/components/embeddings/test_embedding_model_component.py::TestEmbeddingModelComponent::test_build_embeddings_openai_missing_api_key": 8.120289870000079, @@ -430,10 +452,10 @@ "src/backend/tests/unit/components/embeddings/test_embedding_model_component.py::TestEmbeddingModelComponent::test_component_versions[1.1.1]": 8.112025460000268, "src/backend/tests/unit/components/embeddings/test_embedding_model_component.py::TestEmbeddingModelComponent::test_latest_version": 8.215820538000116, "src/backend/tests/unit/components/embeddings/test_embedding_model_component.py::TestEmbeddingModelComponent::test_update_build_config_openai": 8.282516385000008, - "src/backend/tests/unit/components/git/test_git_component.py::test_check_content_pattern": 0.0032370559999890247, - "src/backend/tests/unit/components/git/test_git_component.py::test_check_file_patterns": 0.003056239999978061, - "src/backend/tests/unit/components/git/test_git_component.py::test_combined_filter": 0.003506650999725025, - "src/backend/tests/unit/components/git/test_git_component.py::test_is_binary": 0.0035481679999520566, + "src/backend/tests/unit/components/git/test_git_component.py::test_check_content_pattern": 0.0017698149999887391, + "src/backend/tests/unit/components/git/test_git_component.py::test_check_file_patterns": 0.0016281319999507105, + "src/backend/tests/unit/components/git/test_git_component.py::test_combined_filter": 0.0018094699998982833, + "src/backend/tests/unit/components/git/test_git_component.py::test_is_binary": 0.00180995100004111, "src/backend/tests/unit/components/helpers/test_batch_run_component.py::TestBatchRunComponent::test_add_metadata_failure": 0.004369750999785538, "src/backend/tests/unit/components/helpers/test_batch_run_component.py::TestBatchRunComponent::test_add_metadata_success": 0.004423803999998199, "src/backend/tests/unit/components/helpers/test_batch_run_component.py::TestBatchRunComponent::test_all_versions_have_a_file_name_defined": 0.001901240999586662, @@ -472,96 +494,96 @@ "src/backend/tests/unit/components/helpers/test_structured_output_component.py::TestStructuredOutputComponent::test_with_real_openai_model_nested_schema": 1.9058080820000214, "src/backend/tests/unit/components/helpers/test_structured_output_component.py::TestStructuredOutputComponent::test_with_real_openai_model_simple_schema": 0.960528087000057, "src/backend/tests/unit/components/helpers/test_structured_output_component.py::TestStructuredOutputComponent::test_with_real_openai_model_simple_schema_fail": 0.7785365639999782, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_all_versions_have_a_file_name_defined": 8.145005623000316, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_all_versions_have_a_file_name_defined": 2.0593743389998735, "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_component_versions[1.0.17]": 4.332370791060384, "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_component_versions[1.0.18]": 3.6762167080305517, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_component_versions[1.0.19]": 8.13867578400027, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_component_versions[1.1.0]": 8.123484675999862, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_component_versions[1.1.1]": 10.518107273999703, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_latest_version": 8.106788254000094, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_message_response": 8.032297652000125, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_message_response_ai_sender": 8.059668812999917, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_message_response_with_files": 8.054083885999944, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_message_response_without_session": 8.096649780000007, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_message_storage_disabled": 8.186507217999633, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_all_versions_have_a_file_name_defined": 0.0014594559997931356, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_component_versions[1.0.19]": 2.069089366999947, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_component_versions[1.1.0]": 2.0662825319999456, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_component_versions[1.1.1]": 4.224267936999922, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_latest_version": 2.0346772289999535, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_message_response": 2.0406256989999747, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_message_response_ai_sender": 1.9970043959999657, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_message_response_with_files": 2.0498470549999865, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_message_response_without_session": 2.024454528000092, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestChatInput::test_message_storage_disabled": 2.0315628599998945, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_all_versions_have_a_file_name_defined": 0.0006043170001248654, "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_component_versions[1.0.17]": 0.26945149997482076, "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_component_versions[1.0.18]": 0.28087970800697803, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_component_versions[1.0.19]": 0.03306417399971906, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_component_versions[1.1.0]": 0.031732404999729624, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_component_versions[1.1.1]": 0.03414231600027051, - "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_latest_version": 0.0046855520001827244, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_empty_str_endpoint": 0.0011320649998651788, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_invalid_endpoint": 0.0011190499999429449, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_none_endpoint": 0.0014798040001551271, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[AquilaChat-7B]": 0.0011062749999837251, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[BLOOMZ-7B]": 0.001083673999801249, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ChatGLM2-6B-32K]": 0.0011264229999596864, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[EB-turbo-AppBuilder]": 0.0011130099996989884, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE 3.5]": 0.0010809990001234837, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE Speed-AppBuilder]": 0.0011554960001376458, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE Speed]": 0.0010892850000345788, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-3.5-8K]": 0.0014539750002313667, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-4.0-8K]": 0.0015054410000630014, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Bot-4]": 0.0011028600001736777, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Bot-turbo-AI]": 0.0011251310002080572, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Bot]": 0.0010938630000509875, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Lite-8K-0308]": 0.0010949350000828417, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Speed-128k]": 0.0011102439998467162, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Speed-8K]": 0.0010368069999913132, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Speed]": 0.0011280270000497694, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Llama-2-13b-chat]": 0.001099653999972361, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Llama-2-70b-chat]": 0.0011379859997759922, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Llama-2-7b-chat]": 0.0011344900001404312, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Mixtral-8x7B-Instruct]": 0.0010878529999445163, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Qianfan-BLOOMZ-7B-compressed]": 0.001101087000051848, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Qianfan-Chinese-Llama-2-13B]": 0.00108209099994383, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Qianfan-Chinese-Llama-2-7B]": 0.0011285080001925962, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[XuanYuan-70B-Chat-4bit]": 0.0011101439997673879, - "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Yi-34B-Chat]": 0.000998956000103135, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_all_versions_have_a_file_name_defined": 0.0014177489999838144, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_build_model": 0.005351767999854928, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_build_model_integration": 0.04985503699981564, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_build_model_missing_base_url": 0.004643724000061411, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_component_versions[1.0.19]": 0.0014106759997503104, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_component_versions[1.1.0]": 0.0014252119999582646, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_component_versions[1.1.1]": 0.0014132199999039585, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_get_models_failure": 0.027455526000039754, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_get_models_success": 0.03063550599995324, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_latest_version": 0.00946598200016524, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_update_build_config_keep_alive": 0.004509554000151184, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_update_build_config_mirostat_disabled": 0.004400670999757494, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_update_build_config_mirostat_enabled": 0.004331440999976621, - "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_update_build_config_model_name": 0.12327444300012758, - "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_build_model[0.5-100]": 0.0035262769997643773, - "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_build_model[1.0-500]": 0.003357692000008683, - "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_build_model[1.5-1000]": 0.0033349089997045667, - "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_error_handling": 0.0031266710000181774, - "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_get_models": 0.0036876379999739584, - "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_initialization": 0.002791113999819572, - "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_template": 0.024002506999977413, - "src/backend/tests/unit/components/languagemodels/test_huggingface.py::test_huggingface_inputs": 0.002991738000218902, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_all_versions_have_a_file_name_defined": 0.0013686059999145073, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_build_model": 0.0033658370000466675, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_build_model_error": 0.004689170000119702, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_component_versions[1.0.19]": 0.001384286000075008, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_component_versions[1.1.0]": 0.0018792399998801557, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_component_versions[1.1.1]": 0.001370840999925349, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_get_models": 0.003341310999758207, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_get_models_no_api_key": 0.0030186689998572547, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_initialization": 0.002775826000060988, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_inputs": 0.0029577050004263583, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_json_mode": 0.003683400999989317, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_latest_version": 0.006633120000060444, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_template": 0.025178112000048714, - "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_update_build_config": 0.11250179000012395, - "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_all_versions_have_a_file_name_defined": 8.057034677999809, - "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_build_flow_loop": 9.116735234999851, - "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_component_versions[1.0.19]": 8.195394182999735, - "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_component_versions[1.1.0]": 8.082748373999948, - "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_component_versions[1.1.1]": 8.091156179000336, - "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_latest_version": 8.059849873000076, - "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_run_flow_loop": 9.360945636999759, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_component_versions[1.0.19]": 0.023667360999866105, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_component_versions[1.1.0]": 0.024097610999888275, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_component_versions[1.1.1]": 0.024119803999951728, + "src/backend/tests/unit/components/inputs/test_input_components.py::TestTextInputComponent::test_latest_version": 0.002630187999898226, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_empty_str_endpoint": 0.00041793800005507364, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_invalid_endpoint": 0.0004021089999923788, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_none_endpoint": 0.000697167999874182, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[AquilaChat-7B]": 0.00040215800004261837, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[BLOOMZ-7B]": 0.00039191999997001403, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ChatGLM2-6B-32K]": 0.00038385500010917895, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[EB-turbo-AppBuilder]": 0.00041746800013697793, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE 3.5]": 0.0004299410001067372, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE Speed-AppBuilder]": 0.00041073500005950336, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE Speed]": 0.00039652800001022115, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-3.5-8K]": 0.0004146219999938694, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-4.0-8K]": 0.0003910679999989952, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Bot-4]": 0.0003806679999343032, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Bot-turbo-AI]": 0.00039210099998854275, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Bot]": 0.00037978600005317276, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Lite-8K-0308]": 0.00041193699996711075, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Speed-128k]": 0.0004075790001252244, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Speed-8K]": 0.00041770799998630537, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[ERNIE-Speed]": 0.00041857899998376524, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Llama-2-13b-chat]": 0.00041163599985338806, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Llama-2-70b-chat]": 0.00045008799997958704, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Llama-2-7b-chat]": 0.00038471499999559455, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Mixtral-8x7B-Instruct]": 0.0004297100000485443, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Qianfan-BLOOMZ-7B-compressed]": 0.0007239589999699092, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Qianfan-Chinese-Llama-2-13B]": 0.00042363900001873844, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Qianfan-Chinese-Llama-2-7B]": 0.0003863099999534825, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[XuanYuan-70B-Chat-4bit]": 0.0003852880000749792, + "src/backend/tests/unit/components/languagemodels/test_baidu_qianfan.py::test_qianfan_different_models[Yi-34B-Chat]": 0.00039034700000684097, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_all_versions_have_a_file_name_defined": 0.0006629150000208028, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_build_model": 0.001951693999899362, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_build_model_integration": 0.04039776099989467, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_build_model_missing_base_url": 0.0017451300000175252, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_component_versions[1.0.19]": 0.000699111000017183, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_component_versions[1.1.0]": 0.0006754679999403379, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_component_versions[1.1.1]": 0.0006994019998955991, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_get_models_failure": 0.020693162000156917, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_get_models_success": 0.022854114999972808, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_latest_version": 0.004566212999975505, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_update_build_config_keep_alive": 0.0014923589999398246, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_update_build_config_mirostat_disabled": 0.002491008999982114, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_update_build_config_mirostat_enabled": 0.0013942059999862977, + "src/backend/tests/unit/components/languagemodels/test_chatollama_component.py::TestChatOllamaComponent::test_update_build_config_model_name": 0.10026077999998506, + "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_build_model[0.5-100]": 0.0015172729999903822, + "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_build_model[1.0-500]": 0.0014110270000173841, + "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_build_model[1.5-1000]": 0.001358961000164527, + "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_error_handling": 0.0015282450000313474, + "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_get_models": 0.0013422289998743508, + "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_initialization": 0.0008454549999896699, + "src/backend/tests/unit/components/languagemodels/test_deepseek.py::test_deepseek_template": 0.012690751000036471, + "src/backend/tests/unit/components/languagemodels/test_huggingface.py::test_huggingface_inputs": 0.0010357699999303804, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_all_versions_have_a_file_name_defined": 0.0006803370000625364, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_build_model": 0.0014138230001208285, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_build_model_error": 0.0016495220000933841, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_component_versions[1.0.19]": 0.0006695570000374573, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_component_versions[1.1.0]": 0.0006701979999661489, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_component_versions[1.1.1]": 0.0006741040000406429, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_get_models": 0.0013620669999454549, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_get_models_no_api_key": 0.0009457520000069053, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_initialization": 0.0009458810000069207, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_inputs": 0.0010258689999318449, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_json_mode": 0.0026519279998638012, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_latest_version": 0.003207702000054269, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_template": 0.013022809000062807, + "src/backend/tests/unit/components/languagemodels/test_xai.py::TestXAIComponent::test_update_build_config": 0.24898599400012245, + "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_all_versions_have_a_file_name_defined": 1.9822295269999586, + "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_build_flow_loop": 2.7649436330001436, + "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_component_versions[1.0.19]": 2.028798341999959, + "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_component_versions[1.1.0]": 2.070424707999905, + "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_component_versions[1.1.1]": 2.0045405899999196, + "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_latest_version": 2.014412206000088, + "src/backend/tests/unit/components/logic/test_loop.py::TestLoopComponentWithAPI::test_run_flow_loop": 3.2077608489998966, "src/backend/tests/unit/components/models/test_ChatOllama_component.py::test_build_model": 0.0020211669616401196, "src/backend/tests/unit/components/models/test_ChatOllama_component.py::test_get_model_failure": 0.0068002091138623655, "src/backend/tests/unit/components/models/test_ChatOllama_component.py::test_get_model_success": 0.015780292043928057, @@ -614,28 +636,28 @@ "src/backend/tests/unit/components/models/test_deepseek.py::test_deepseek_get_models": 0.0036159830001452065, "src/backend/tests/unit/components/models/test_deepseek.py::test_deepseek_initialization": 0.0030138490001263563, "src/backend/tests/unit/components/models/test_deepseek.py::test_deepseek_template": 0.02356655199969282, - "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_all_versions_have_a_file_name_defined": 8.179511470999842, - "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_build_embeddings_openai": 8.123162658999945, - "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_build_embeddings_openai_missing_api_key": 8.026384709000013, - "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_build_embeddings_unknown_provider": 8.29559119099963, - "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_component_versions[1.0.19]": 8.043992962999937, - "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_component_versions[1.1.0]": 8.190444700999933, - "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_component_versions[1.1.1]": 8.075870885000313, - "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_latest_version": 10.51063653500023, - "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_update_build_config_openai": 8.08047182900009, + "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_all_versions_have_a_file_name_defined": 2.0592932690000225, + "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_build_embeddings_openai": 2.130430585000113, + "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_build_embeddings_openai_missing_api_key": 2.0490007439999545, + "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_build_embeddings_unknown_provider": 2.1189676950000376, + "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_component_versions[1.0.19]": 2.0520491699999184, + "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_component_versions[1.1.0]": 2.068122266000046, + "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_component_versions[1.1.1]": 2.0413159750000887, + "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_latest_version": 4.5469731879999244, + "src/backend/tests/unit/components/models/test_embedding_model_component.py::TestEmbeddingModelComponent::test_update_build_config_openai": 2.0984183840000696, "src/backend/tests/unit/components/models/test_huggingface.py::test_huggingface_inputs": 0.002935343000217472, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_all_versions_have_a_file_name_defined": 8.446822823000048, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_build_model_anthropic": 8.319300722000207, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_build_model_anthropic_missing_api_key": 12.796845204999954, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_build_model_openai": 8.7665227089999, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_build_model_openai_missing_api_key": 10.32622657700017, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_build_model_unknown_provider": 9.036449172999937, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_component_versions[1.0.19]": 8.312321239000084, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_component_versions[1.1.0]": 8.730595002999962, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_component_versions[1.1.1]": 8.35393661299986, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_latest_version": 8.360651149999967, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_update_build_config_anthropic": 8.846111160999726, - "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_update_build_config_openai": 11.669300608999947, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_all_versions_have_a_file_name_defined": 2.0273027780000348, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_build_model_anthropic": 2.072215417999928, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_build_model_anthropic_missing_api_key": 1.2509235339999805, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_build_model_openai": 2.102755736000063, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_build_model_openai_missing_api_key": 2.078545233, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_build_model_unknown_provider": 1.264502769000046, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_component_versions[1.0.19]": 2.0472047669999256, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_component_versions[1.1.0]": 2.047802461999936, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_component_versions[1.1.1]": 2.0497915850000936, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_latest_version": 2.0731787290001193, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_update_build_config_anthropic": 4.903791860999945, + "src/backend/tests/unit/components/models/test_language_model_component.py::TestLanguageModelComponent::test_update_build_config_openai": 2.0999757689999115, "src/backend/tests/unit/components/models/test_xai.py::TestXAIComponent::test_all_versions_have_a_file_name_defined": 0.0014568770002370002, "src/backend/tests/unit/components/models/test_xai.py::TestXAIComponent::test_build_model": 0.003458199999840872, "src/backend/tests/unit/components/models/test_xai.py::TestXAIComponent::test_build_model_error": 0.0043968889999632665, @@ -650,17 +672,17 @@ "src/backend/tests/unit/components/models/test_xai.py::TestXAIComponent::test_latest_version": 0.006742511999846101, "src/backend/tests/unit/components/models/test_xai.py::TestXAIComponent::test_template": 0.025210852999862254, "src/backend/tests/unit/components/models/test_xai.py::TestXAIComponent::test_update_build_config": 0.4465963840000313, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_all_versions_have_a_file_name_defined": 8.94631701000003, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_component_versions[1.0.19]": 9.15513474599993, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_component_versions[1.1.0]": 7.629844162999689, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_component_versions[1.1.1]": 7.907987696999953, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_invalid_input": 12.497814846999518, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_latest_version": 7.580384431999846, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_process_data_input": 7.53349160200014, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_process_dataframe_input": 11.451186320000033, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_process_list_input": 10.856783212999744, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_process_message_input": 11.31106706100013, - "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_process_string_input": 8.008707321000202, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_all_versions_have_a_file_name_defined": 1.2437934030000406, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_component_versions[1.0.19]": 1.2549795480000512, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_component_versions[1.1.0]": 1.2367088000000876, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_component_versions[1.1.1]": 1.2642950629999632, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_invalid_input": 1.2564508770000202, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_latest_version": 1.3068663149999793, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_process_data_input": 1.2919342870000037, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_process_dataframe_input": 1.3053097679999155, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_process_list_input": 1.2886664019999898, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_process_message_input": 1.2559006210000234, + "src/backend/tests/unit/components/outputs/test_chat_output_component.py::TestChatOutput::test_process_string_input": 1.2772376770000164, "src/backend/tests/unit/components/outputs/test_output_components.py::TestChatOutput::test_all_versions_have_a_file_name_defined": 4.963613892000012, "src/backend/tests/unit/components/outputs/test_output_components.py::TestChatOutput::test_component_versions[1.0.17]": 3.6106157921021804, "src/backend/tests/unit/components/outputs/test_output_components.py::TestChatOutput::test_component_versions[1.0.18]": 3.6919090420706198, @@ -668,133 +690,151 @@ "src/backend/tests/unit/components/outputs/test_output_components.py::TestChatOutput::test_component_versions[1.1.0]": 4.997824592000029, "src/backend/tests/unit/components/outputs/test_output_components.py::TestChatOutput::test_component_versions[1.1.1]": 5.098571616000072, "src/backend/tests/unit/components/outputs/test_output_components.py::TestChatOutput::test_latest_version": 6.680932718999998, - "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_all_versions_have_a_file_name_defined": 0.0014980340001784498, + "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_all_versions_have_a_file_name_defined": 0.0006777510000119946, "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_component_versions[1.0.17]": 0.27941045799525455, "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_component_versions[1.0.18]": 0.24612879107007757, - "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_component_versions[1.0.19]": 0.11461898999959885, - "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_component_versions[1.1.0]": 0.11050012700025036, - "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_component_versions[1.1.1]": 0.03539225000031365, - "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_latest_version": 0.005118848000165599, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_all_versions_have_a_file_name_defined": 0.0016662380007801403, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_append_update": 0.002884991999962949, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_combine": 0.0029312080000636342, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_combine_with_overlapping_keys": 0.002915488999860827, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_component_versions[1.0.19]": 0.0016546959996048827, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_component_versions[1.1.0]": 0.0015963379996719596, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_component_versions[1.1.1]": 0.0016020779999053048, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_filter_values": 0.0029267889999573526, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_get_normalized_data": 0.002850969000519399, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_latest_version": 0.009122165000007953, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_literal_eval": 0.003011006000178895, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_no_actions": 0.002859534999970492, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_remove_keys": 0.002995497000483738, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_rename_keys": 0.0030132110000522516, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_select_keys": 0.0031428120000782656, - "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_validate_single_data_with_multiple_data": 0.003051582000352937, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_all_versions_have_a_file_name_defined": 0.0015800379997017444, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_basic_setup": 0.0025246990003324754, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_build_dataframe_basic": 0.0034869930000240856, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_component_versions[1.0.19]": 0.0016077680002126726, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_component_versions[1.1.0]": 0.0015592870004184078, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_component_versions[1.1.1]": 0.0020613239998965582, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_data_without_data_dict": 0.002919055999882403, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_data_without_text": 0.0029982930004734953, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_empty_data_list": 0.0029754700008197688, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_invalid_input_type": 0.0024106559999381716, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_latest_version": 0.005785561999800848, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_mixed_data_fields": 0.003333308000037505, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_single_data_input": 0.0030813579996902263, - "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_status_update": 0.003036644000076194, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_empty_dataframe": 0.002877589000036096, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_invalid_operation": 0.0026940260004266747, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_non_existent_column": 0.0028613089993996255, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Add Column-expected_columns0-expected_values0]": 0.0038622049996774876, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Drop Column-expected_columns1-None]": 0.0036385970001902024, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Filter-expected_columns2-expected_values2]": 0.003618538999944576, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Head-expected_columns6-expected_values6]": 0.003263969000272482, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Rename Column-expected_columns4-None]": 0.0033504699995319243, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Replace Value-expected_columns8-expected_values8]": 0.0035705010004676296, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Select Columns-expected_columns5-None]": 0.0035511539995241037, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Sort-expected_columns3-expected_values3]": 0.003481344000192621, - "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Tail-expected_columns7-expected_values7]": 0.0032000800001696916, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_all_versions_have_a_file_name_defined": 0.0018460329993104097, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_component_versions[1.0.19]": 0.0018021330001829483, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_component_versions[1.1.0]": 0.0017217409999830124, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_component_versions[1.1.1]": 0.0021451229999911448, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_get_data_structure": 0.004018386999632639, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_invalid_lambda_response": 0.008170992000032129, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_lambda_with_complex_data_structure": 0.008174547999715287, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_lambda_with_large_dataset": 0.013371592999646964, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_latest_version": 0.008780279999882623, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_successful_lambda_generation": 0.008488945000408421, - "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_validate_lambda": 0.003977038999892102, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_all_versions_have_a_file_name_defined": 0.0024149440000655886, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_async_invocation": 0.0041796570003498346, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_component_versions[1.0.19]": 0.0019307319998915773, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_component_versions[1.1.0]": 0.003091916999892419, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_component_versions[1.1.1]": 0.001998949000153516, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_empty_dataframe": 0.003031944999293046, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_invalid_template_keys": 0.003093208999871422, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_large_dataframe": 0.4180708720000439, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_latest_version": 0.006182724000154849, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_multiple_column_template": 0.0033755380000002333, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_nan_values": 0.003321807000247645, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_parse_with_custom_separator": 0.003128386000298633, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_parse_with_custom_template": 0.0032252659998448507, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_successful_parse_with_default_template": 0.003448692999427294, - "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_various_data_types": 0.005348276999939117, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_all_versions_have_a_file_name_defined": 0.002219460000105755, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_clean_data_with_stringify": 0.00458636600023965, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_component_versions[1.0.19]": 0.0020792800000890566, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_component_versions[1.1.0]": 0.0026174629997512966, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_component_versions[1.1.1]": 0.0020916910002597433, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_invalid_input_type": 0.0031474719999096124, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_invalid_template": 0.003343746000155079, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_latest_version": 0.007151109999540495, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_multiple_rows_with_custom_separator": 0.003584617000342405, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_none_input": 0.003013814000041748, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_parse_data_object": 0.0029739569995399506, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_parse_dataframe": 0.003286651000053098, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_stringify_data_object": 0.003021475999503309, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_stringify_dataframe": 0.0044266670001889, - "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_stringify_message_object": 0.00297258500040698, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_all_versions_have_a_file_name_defined": 0.0014834069997959887, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_component_versions[1.0.19]": 0.0014794400003665942, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_component_versions[1.1.0]": 0.002049091000117187, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_component_versions[1.1.1]": 0.0014814230003139528, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_empty_input_text": 0.003005476999987877, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_get_matches_text_invalid_pattern": 0.0030830420000711456, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_get_matches_text_no_matches": 0.0031969629994819115, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_get_matches_text_output": 0.003168961000028503, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_invalid_regex_pattern": 0.0031107340000744443, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_latest_version": 0.006622384999445785, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_no_matches_found": 0.003089090999765176, - "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_successful_regex_extraction": 0.0032738170002630795, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-csv-.csv]": 0.00027201799957765616, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-json-.json]": 0.000242091000018263, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-markdown-.markdown]": 0.000839455999994243, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-txt-.txt]": 0.00026166699990426423, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_expands_home": 0.0002476519994161208, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_handles_incorrect_or_excel_add[./test_output-excel-./test_output.xlsx]": 0.000245537999944645, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_handles_incorrect_or_excel_add[./test_output.txt-csv-./test_output.txt.csv]": 0.00024367400010305573, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_handles_incorrect_or_excel_add[./test_output.txt-excel-./test_output.txt.xlsx]": 0.00026527499949224875, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_correct_extension[./test_output.csv-csv]": 0.0002494350001143175, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_correct_extension[./test_output.json-json]": 0.00024152099967977847, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_correct_extension[./test_output.markdown-markdown]": 0.00025104799988184823, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_correct_extension[./test_output.txt-txt]": 0.0002730899996095104, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_excel_extension[./test_output.xls]": 0.00024144200006048777, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_excel_extension[./test_output.xlsx]": 0.0002502269999240525, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_all_versions_have_a_file_name_defined": 0.0002565390000199841, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_basic_setup": 0.0002496459997018974, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_component_versions[1.0.19]": 0.00027727700035029557, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_component_versions[1.1.0]": 0.00025595599981897976, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_component_versions[1.1.1]": 0.00024725999992369907, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_directory_creation": 0.00024589899976490415, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_invalid_input_type": 0.0002449070002512599, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_latest_version": 0.0002924559998973564, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_save_data": 0.00024532899988116696, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_save_message": 0.0002623989998937759, - "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_update_build_config_dataframe": 0.0002488340001036704, + "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_component_versions[1.0.19]": 0.024899696999909793, + "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_component_versions[1.1.0]": 0.026248830999975326, + "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_component_versions[1.1.1]": 0.02345536199993603, + "src/backend/tests/unit/components/outputs/test_output_components.py::TestTextOutputComponent::test_latest_version": 0.0028494050000063, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_add_metadata_failure": 0.0011957969999230045, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_add_metadata_success": 0.001206897999963985, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_all_versions_have_a_file_name_defined": 0.001055815999961851, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_batch_run_error_with_metadata": 0.0016468270000586926, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_batch_run_error_without_metadata": 0.0015536329999576992, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_batch_run_without_metadata": 0.002857901999959722, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_component_versions[1.0.19]": 0.0010031179999714368, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_component_versions[1.1.0]": 0.0010594429999173371, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_component_versions[1.1.1]": 0.000991956999996546, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_create_base_row": 0.001209712000104446, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_empty_dataframe": 0.002430875999948512, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_invalid_column_name": 0.0024132250000548083, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_latest_version": 0.004349801000103071, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_metadata_disabled": 0.0012173959997880957, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_non_string_column_conversion": 0.003196643000023869, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_operational_error_with_metadata": 0.002456946000052085, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_operational_error_without_metadata": 0.002307898999902136, + "src/backend/tests/unit/components/processing/test_batch_run_component.py::TestBatchRunComponent::test_successful_batch_run_with_system_message": 0.003380164000077457, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_all_versions_have_a_file_name_defined": 0.0007101329999841255, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_append_update": 0.000989111999956549, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_combine": 0.0009844129998555218, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_combine_with_overlapping_keys": 0.0009667790000094101, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_component_versions[1.0.19]": 0.0007030289999647721, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_component_versions[1.1.0]": 0.0007018170000492319, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_component_versions[1.1.1]": 0.000688450999973611, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_filter_values": 0.0009777810000741738, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_get_normalized_data": 0.0009535760000289883, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_latest_version": 0.004561994999903618, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_literal_eval": 0.0010366619999331306, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_no_actions": 0.0009237299999540483, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_remove_keys": 0.0009881999999379332, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_rename_keys": 0.0009734120000075563, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_select_keys": 0.0010068349999983184, + "src/backend/tests/unit/components/processing/test_data_operations_component.py::TestDataOperationsComponent::test_validate_single_data_with_multiple_data": 0.0010340250000808737, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_all_versions_have_a_file_name_defined": 0.0007020379998721182, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_basic_setup": 0.000818684000137182, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_build_dataframe_basic": 0.0015392859997973574, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_component_versions[1.0.19]": 0.0007153529999186503, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_component_versions[1.1.0]": 0.0007134180000321066, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_component_versions[1.1.1]": 0.0010496349999584709, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_data_without_data_dict": 0.0012036210001724612, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_data_without_text": 0.0012317830000938557, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_empty_data_list": 0.0011750970001003225, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_invalid_input_type": 0.0008451540001033209, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_latest_version": 0.0025093529999367092, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_mixed_data_fields": 0.0014303930000778564, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_single_data_input": 0.0012962440000592323, + "src/backend/tests/unit/components/processing/test_data_to_dataframe_component.py::TestDataToDataFrameComponent::test_status_update": 0.0012215949999472286, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_empty_dataframe": 0.0010818850000759994, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_invalid_operation": 0.0009657479999987117, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_non_existent_column": 0.0010275030000457264, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Add Column-expected_columns0-expected_values0]": 0.0017273470000418456, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Drop Column-expected_columns1-None]": 0.00167941699999119, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Filter-expected_columns2-expected_values2]": 0.0016480389999742329, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Head-expected_columns6-expected_values6]": 0.0014022710000745064, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Rename Column-expected_columns4-None]": 0.0014427260000502429, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Replace Value-expected_columns8-expected_values8]": 0.0015724880000789199, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Select Columns-expected_columns5-None]": 0.0016046690000166564, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Sort-expected_columns3-expected_values3]": 0.0015496350000603343, + "src/backend/tests/unit/components/processing/test_dataframe_operations.py::test_operations[Tail-expected_columns7-expected_values7]": 0.0013863620000620358, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_all_versions_have_a_file_name_defined": 0.0008456359998945118, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_component_versions[1.0.19]": 0.0008463959999289727, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_component_versions[1.1.0]": 0.0008310780000329032, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_component_versions[1.1.1]": 0.0008421070001531916, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_get_data_structure": 0.0011362559999952282, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_invalid_lambda_response": 0.0035155659999190902, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_lambda_with_complex_data_structure": 0.0035690260001501883, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_lambda_with_large_dataset": 0.007047403000001395, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_latest_version": 0.003382287999897926, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_successful_lambda_generation": 0.004045494000024519, + "src/backend/tests/unit/components/processing/test_lambda_filter.py::TestLambdaFilterComponent::test_validate_lambda": 0.0010970229999429648, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_all_versions_have_a_file_name_defined": 0.000991545999909249, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_async_invocation": 0.0017713390000153595, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_component_versions[1.0.19]": 0.0009849239999084602, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_component_versions[1.1.0]": 0.0010052019999875483, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_component_versions[1.1.1]": 0.0009842330000537913, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_empty_dataframe": 0.0014034440000614268, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_invalid_template_keys": 0.0014214760000186288, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_large_dataframe": 0.25921934600000895, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_latest_version": 0.002904558999944129, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_multiple_column_template": 0.0016451030001007894, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_nan_values": 0.0015798420000692204, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_parse_with_custom_separator": 0.0015546760000688664, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_parse_with_custom_template": 0.0016299260000778304, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_successful_parse_with_default_template": 0.0016599220000443893, + "src/backend/tests/unit/components/processing/test_parse_dataframe_component.py::TestParseDataFrameComponent::test_various_data_types": 0.0030305840000437456, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_all_versions_have_a_file_name_defined": 0.0011077530000420666, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_clean_data_with_stringify": 0.002425957000014023, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_component_versions[1.0.19]": 0.001596201000097608, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_component_versions[1.1.0]": 0.0011121210001192594, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_component_versions[1.1.1]": 0.001082013999962328, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_invalid_input_type": 0.001360452999847439, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_invalid_template": 0.001568439999914517, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_latest_version": 0.0038995500000282846, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_multiple_rows_with_custom_separator": 0.0017626520000249002, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_none_input": 0.0013041379999094715, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_parse_data_object": 0.0012889399999949092, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_parse_dataframe": 0.0014645270000528399, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_stringify_data_object": 0.0013015720001021691, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_stringify_dataframe": 0.0024655899998151654, + "src/backend/tests/unit/components/processing/test_parser_component.py::TestParserComponent::test_stringify_message_object": 0.0013506340000049022, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_all_versions_have_a_file_name_defined": 0.0006613310000602723, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_component_versions[1.0.19]": 0.0006886120000899609, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_component_versions[1.1.0]": 0.0006738050000194562, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_component_versions[1.1.1]": 0.0006799560001127247, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_empty_input_text": 0.0008172419999254998, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_get_matches_text_invalid_pattern": 0.0008989730000621421, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_get_matches_text_no_matches": 0.0008974409998927513, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_get_matches_text_output": 0.0008968010000671711, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_invalid_regex_pattern": 0.0008447129999922254, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_latest_version": 0.0028479630000219913, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_no_matches_found": 0.0008571959999699175, + "src/backend/tests/unit/components/processing/test_regex_component.py::TestRegexExtractorComponent::test_successful_regex_extraction": 0.0009360520000427641, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-csv-.csv]": 0.0002117450000014287, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-json-.json]": 0.00021611099998608552, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-markdown-.markdown]": 0.00020094400008474622, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-txt-.txt]": 0.00020208699993418122, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_expands_home": 0.00019979199998942931, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_handles_incorrect_or_excel_add[./test_output-excel-./test_output.xlsx]": 0.00021790600010263006, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_handles_incorrect_or_excel_add[./test_output.txt-csv-./test_output.txt.csv]": 0.00019983200013484748, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_handles_incorrect_or_excel_add[./test_output.txt-excel-./test_output.txt.xlsx]": 0.00020076299995253066, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_correct_extension[./test_output.csv-csv]": 0.0001962149998462337, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_correct_extension[./test_output.json-json]": 0.000203059000000394, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_correct_extension[./test_output.markdown-markdown]": 0.00020283799995013396, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_correct_extension[./test_output.txt-txt]": 0.0002001619998281967, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_excel_extension[./test_output.xls]": 0.00020384000004014524, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_adjust_path_keeps_existing_excel_extension[./test_output.xlsx]": 0.0002115250000542801, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_all_versions_have_a_file_name_defined": 0.00019614499990439072, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_basic_setup": 0.00020437100010894937, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_component_versions[1.0.19]": 0.00021060199992462003, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_component_versions[1.1.0]": 0.0005912799999805429, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_component_versions[1.1.1]": 0.0002013239998177596, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_directory_creation": 0.0001974269999891476, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_invalid_input_type": 0.00020165500006896764, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_latest_version": 0.00020001299992600252, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_save_data": 0.0001960639999651903, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_save_message": 0.0001947120000522773, + "src/backend/tests/unit/components/processing/test_save_file_component.py::TestSaveToFileComponent::test_update_build_config_dataframe": 0.00020156499988388532, "src/backend/tests/unit/components/processing/test_save_to_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-csv-.csv]": 0.0028634599998440535, "src/backend/tests/unit/components/processing/test_save_to_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-json-.json]": 0.002895288999980039, "src/backend/tests/unit/components/processing/test_save_to_file_component.py::TestSaveToFileComponent::test_adjust_path_adds_extension[./test_output-markdown-.markdown]": 0.002877976999798193, @@ -820,90 +860,130 @@ "src/backend/tests/unit/components/processing/test_save_to_file_component.py::TestSaveToFileComponent::test_save_data": 0.004565492999972776, "src/backend/tests/unit/components/processing/test_save_to_file_component.py::TestSaveToFileComponent::test_save_message": 0.010504567999987557, "src/backend/tests/unit/components/processing/test_save_to_file_component.py::TestSaveToFileComponent::test_update_build_config_dataframe": 0.002705645000332879, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_all_versions_have_a_file_name_defined": 0.0014701720001539798, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_component_versions[1.0.19]": 0.09416465599952062, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_component_versions[1.1.0]": 0.10098047100018448, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_component_versions[1.1.1]": 0.03731609700025729, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_latest_version": 0.0064016110000011395, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_all_versions_have_a_file_name_defined": 0.000669226000013623, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_component_versions[1.0.19]": 0.026541517000055137, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_component_versions[1.1.0]": 0.026582962999896154, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_component_versions[1.1.1]": 0.023654380000039055, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_latest_version": 0.003051181000046199, "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_as_dataframe": 0.0033914260002347874, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_basic": 0.002813679000155389, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_custom_separator": 0.0025088110000979214, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_empty_input": 0.0022006249996593397, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_multiple_inputs": 0.002536211000460753, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_single_chunk": 0.0022202329996616754, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_with_dataframe_input": 0.0034563969998089306, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_with_metadata": 0.0022232869996514637, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_with_overlap": 0.002281526000388112, - "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_with_url_loader": 2.1216742699998576, - "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_all_versions_have_a_file_name_defined": 11.378274203000274, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_basic": 0.0017287779999151098, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_custom_separator": 0.001678334999951403, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_empty_input": 0.0012698540000428693, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_multiple_inputs": 0.0015180359998794302, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_single_chunk": 0.001253655000141407, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_with_dataframe_input": 0.0019966370000474853, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_with_metadata": 0.001577697999891825, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_split_text_with_overlap": 0.0013939549999122391, + "src/backend/tests/unit/components/processing/test_split_text_component.py::TestSplitTextComponent::test_with_url_loader": 1.4363001020000183, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_all_versions_have_a_file_name_defined": 0.000664867999944363, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_build_structured_output_data_object_properties": 0.010425779999991391, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_build_structured_output_fails_when_base_returns_non_list": 0.008794151000074635, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_build_structured_output_returns_data_with_dict": 0.01086807299998327, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_build_structured_output_returns_data_with_single_item": 0.00881216699997367, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_component_versions[1.0.19]": 0.0006369470000890942, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_component_versions[1.1.0]": 0.0006231199998865122, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_component_versions[1.1.1]": 0.0006353830000307426, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_correctly_builds_output_model": 0.0015517990000262216, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_empty_output_schema": 0.0009659290000172405, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_handles_multiple_outputs": 0.0014852250000103595, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_invalid_output_schema_type": 0.0009586150000586713, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_large_input_value": 0.008989197000005333, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_latest_version": 0.003682695999941643, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_nested_output_schema": 0.010040414000059172, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_raises_value_error_for_unsupported_language_model": 0.0010864729998729672, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_structured_output_handles_empty_responses_array": 0.00851431099988531, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_structured_output_returns_dict_when_no_objects_key": 0.009234702999833644, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_structured_output_returns_direct_response_when_not_dict": 0.010042727999802992, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_successful_structured_output_generation_with_patch_with_config": 0.019358613000122205, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_with_real_nvidia_model_simple_schema": 0.00021897700003137288, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_with_real_openai_model_complex_schema": 1.4660667659999262, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_with_real_openai_model_nested_schema": 2.7865310749999708, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_with_real_openai_model_simple_schema": 0.9337310070000058, + "src/backend/tests/unit/components/processing/test_structured_output_component.py::TestStructuredOutputComponent::test_with_real_openai_model_simple_schema_fail": 0.317121459999953, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_all_versions_have_a_file_name_defined": 0.0006277499998077474, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_component_versions[1.0.19]": 0.0006276689999822338, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_component_versions[1.1.0]": 0.0006128600000465667, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_component_versions[1.1.1]": 0.0006257849998974052, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_data_to_data": 0.0007341760000372233, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_data_to_dataframe": 0.0010926840000138327, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_data_to_message": 0.0008024439999871902, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_dataframe_to_data": 0.001280223999970076, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_dataframe_to_dataframe": 0.0011738050001213196, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_dataframe_to_message": 0.0038028309999162957, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_latest_version": 0.0028258700001515535, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_message_to_data": 0.000797314000010374, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_message_to_dataframe": 0.001694606000000931, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_message_to_message": 0.0008078240000486403, + "src/backend/tests/unit/components/processing/test_type_converter_component.py::TestTypeConverterComponent::test_update_outputs": 0.0008576559999937672, + "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_all_versions_have_a_file_name_defined": 1.279996643000004, "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_component_versions[1.0.17]": 15.071019583090674, "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_component_versions[1.0.18]": 5.277748624968808, - "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_component_versions[1.0.19]": 11.30676091999976, - "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_component_versions[1.1.0]": 10.930969661999825, - "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_component_versions[1.1.1]": 15.986898750999899, - "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_latest_version": 11.269573996999952, - "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_post_code_processing": 9.009119962000113, - "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_prompt_component_latest": 7.352621749000264, - "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_build_data": 0.0022810250002294197, - "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_get_data": 0.001836648000335117, - "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_update_build_config": 0.0026156499998251093, - "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_update_build_config_exceed_limit": 0.0020041480001964374, - "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_validate_text_key_invalid": 0.0019744739997804572, - "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_validate_text_key_valid": 0.0018241939997096779, - "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_build_data": 0.0026997159993698006, - "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_get_data": 0.002288548999786144, - "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_update_build_config": 0.0025021380001817306, - "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_update_build_config_exceed_limit": 0.0023073430002114037, - "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_validate_text_key_invalid": 0.0022769279999010905, - "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_validate_text_key_valid": 0.0022994890005065827, - "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_all_versions_have_a_file_name_defined": 7.510390122999979, - "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_build_query_url": 7.627358630999879, - "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_component_initialization": 7.684947008999643, - "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_component_versions": 7.651335364999795, - "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_invalid_url_handling": 7.390487266999571, - "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_latest_version": 7.332524573000228, - "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_parse_atom_response": 7.4258192530001, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_all_versions_have_a_file_name_defined": 0.00156162600069365, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_build_method": 0.0027192369993827015, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_component_initialization": 0.005942744000094535, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_component_versions[1.0.19]": 0.0014327150001918199, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_component_versions[1.1.0]": 0.0014258109999900626, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_component_versions[1.1.1]": 0.001412135999999009, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_latest_version": 0.0029629610003212292, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_search_google_error_handling": 0.004314854999847739, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_search_google_invalid_api_key": 0.002880186000311369, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_search_google_invalid_cse_id": 0.0028680149998763227, - "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_search_google_success": 0.007847449999644596, - "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_build_method": 0.002000855999540363, - "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_build_wrapper": 0.002039617999798793, - "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_component_initialization": 0.0020894110007247946, - "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_search_serper_error_handling": 0.003168385000208218, - "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_search_serper_success": 0.003508791000513156, - "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_text_search_serper": 0.004029834000448318, - "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_all_versions_have_a_file_name_defined": 0.0014003750002302695, - "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_component_versions[1.0.19]": 0.0013919779999014281, - "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_component_versions[1.1.0]": 0.0013990110001032008, - "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_component_versions[1.1.1]": 0.0014094719995227933, - "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_fetch_content_empty_response": 0.0027531499995347986, - "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_fetch_content_error_handling": 0.0022874009996485256, - "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_fetch_content_success": 0.002561301000241656, - "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_latest_version": 0.004886133000127302, - "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_wikidata_initialization": 0.0017486249998910353, - "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_wikidata_template": 0.01239549099955184, - "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_all_versions_have_a_file_name_defined": 0.0016232399998443725, - "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_component_versions[1.0.19]": 0.0015681380000387435, - "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_component_versions[1.1.0]": 0.0015345739998338104, - "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_component_versions[1.1.1]": 0.001566263999848161, - "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_fetch_content": 0.003051999000035721, - "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_latest_version": 0.0061860079995312844, - "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_wikipedia_error_handling": 0.0021936359994469967, - "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_wikipedia_initialization": 0.0030909200004316517, - "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_wikipedia_template": 0.013464716999806114, - "src/backend/tests/unit/components/search/test_yfinance_tool.py::TestYfinanceComponent::test_error_handling": 0.0021389730000009877, - "src/backend/tests/unit/components/search/test_yfinance_tool.py::TestYfinanceComponent::test_fetch_info": 0.0023390380001728772, - "src/backend/tests/unit/components/search/test_yfinance_tool.py::TestYfinanceComponent::test_fetch_news": 0.002171434999581834, - "src/backend/tests/unit/components/search/test_yfinance_tool.py::TestYfinanceComponent::test_initialization": 0.0018807820001711661, - "src/backend/tests/unit/components/search/test_yfinance_tool.py::TestYfinanceComponent::test_template_structure": 0.0580708429997685, + "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_component_versions[1.0.19]": 1.3002803600001016, + "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_component_versions[1.1.0]": 1.304123367000102, + "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_component_versions[1.1.1]": 1.2881436889998668, + "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_latest_version": 1.2646013079998966, + "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_post_code_processing": 1.3663131230000545, + "src/backend/tests/unit/components/prompts/test_prompt_component.py::TestPromptComponent::test_prompt_component_latest": 1.3498473439999543, + "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_build_data": 0.0010334240000702266, + "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_get_data": 0.0006619629998567689, + "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_update_build_config": 0.0010952299999189563, + "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_update_build_config_exceed_limit": 0.0007669489999670986, + "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_validate_text_key_invalid": 0.0007037210000362393, + "src/backend/tests/unit/components/prototypes/test_create_data_component.py::test_validate_text_key_valid": 0.0006385210000416919, + "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_build_data": 0.000975134999976035, + "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_get_data": 0.0006761780000488216, + "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_update_build_config": 0.00076650799996969, + "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_update_build_config_exceed_limit": 0.0006898249998812389, + "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_validate_text_key_invalid": 0.0006666110000423942, + "src/backend/tests/unit/components/prototypes/test_update_data_component.py::test_validate_text_key_valid": 0.000653527000054055, + "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_all_versions_have_a_file_name_defined": 1.2745537509998712, + "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_build_query_url": 1.3670082030000685, + "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_component_initialization": 1.2992355359999692, + "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_component_versions": 1.3120956949999254, + "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_invalid_url_handling": 1.319215512000028, + "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_latest_version": 1.3294719809999833, + "src/backend/tests/unit/components/search/test_arxiv_component.py::TestArXivComponent::test_parse_atom_response": 1.3152049130000023, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_all_versions_have_a_file_name_defined": 0.0007929060000151367, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_build_method": 0.0007588529999793536, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_component_initialization": 0.003114961000051153, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_component_versions[1.0.19]": 0.000755395999931352, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_component_versions[1.1.0]": 0.0007259519999252007, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_component_versions[1.1.1]": 0.0006216369999947347, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_latest_version": 0.0011196550000249772, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_search_google_error_handling": 0.0026400759999205548, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_search_google_invalid_api_key": 0.001165068999966934, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_search_google_invalid_cse_id": 0.0011416950000011639, + "src/backend/tests/unit/components/search/test_google_search_api.py::TestGoogleSearchAPICore::test_search_google_success": 0.0054267550000304254, + "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_build_method": 0.0006218180001269502, + "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_build_wrapper": 0.000658756000007088, + "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_component_initialization": 0.0006591969998908098, + "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_search_serper_error_handling": 0.0014258049999398281, + "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_search_serper_success": 0.001783339999974487, + "src/backend/tests/unit/components/search/test_google_serper_api_core.py::test_text_search_serper": 0.0019023929999093525, + "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_all_versions_have_a_file_name_defined": 0.0006204360000765519, + "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_component_versions[1.0.19]": 0.0006124800000861796, + "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_component_versions[1.1.0]": 0.0006176089999598844, + "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_component_versions[1.1.1]": 0.0006342699999777324, + "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_fetch_content_empty_response": 0.0012640640001109205, + "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_fetch_content_error_handling": 0.0009416139999984807, + "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_fetch_content_success": 0.0013054409999995187, + "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_latest_version": 0.002712460999987343, + "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_wikidata_initialization": 0.0007390350001514889, + "src/backend/tests/unit/components/search/test_wikidata_api.py::TestWikidataComponent::test_wikidata_template": 0.006393245000026582, + "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_all_versions_have_a_file_name_defined": 0.0006254340000850789, + "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_component_versions[1.0.19]": 0.00061480500005473, + "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_component_versions[1.1.0]": 0.0005937260000337119, + "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_component_versions[1.1.1]": 0.0009555289999525485, + "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_fetch_content": 0.00144217500007926, + "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_latest_version": 0.00254655300000195, + "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_wikipedia_error_handling": 0.0009467929999118496, + "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_wikipedia_initialization": 0.0007736319998912222, + "src/backend/tests/unit/components/search/test_wikipedia_api.py::TestWikipediaComponent::test_wikipedia_template": 0.006388566000055107, + "src/backend/tests/unit/components/search/test_yfinance_tool.py::TestYfinanceComponent::test_error_handling": 0.0010384749999730047, + "src/backend/tests/unit/components/search/test_yfinance_tool.py::TestYfinanceComponent::test_fetch_info": 0.0010887480000292271, + "src/backend/tests/unit/components/search/test_yfinance_tool.py::TestYfinanceComponent::test_fetch_news": 0.0010534729999562842, + "src/backend/tests/unit/components/search/test_yfinance_tool.py::TestYfinanceComponent::test_initialization": 0.0006831230000443611, + "src/backend/tests/unit/components/search/test_yfinance_tool.py::TestYfinanceComponent::test_template_structure": 0.013927865999903588, "src/backend/tests/unit/components/tools/test_arxiv_component.py::TestArXivComponent::test_all_versions_have_a_file_name_defined": 7.719283441000016, "src/backend/tests/unit/components/tools/test_arxiv_component.py::TestArXivComponent::test_build_query_url": 7.880579604000104, "src/backend/tests/unit/components/tools/test_arxiv_component.py::TestArXivComponent::test_component_initialization": 7.921767463000151, @@ -911,17 +991,17 @@ "src/backend/tests/unit/components/tools/test_arxiv_component.py::TestArXivComponent::test_invalid_url_handling": 7.964883273999703, "src/backend/tests/unit/components/tools/test_arxiv_component.py::TestArXivComponent::test_latest_version": 7.6661638979999225, "src/backend/tests/unit/components/tools/test_arxiv_component.py::TestArXivComponent::test_parse_atom_response": 7.974242982000078, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_all_versions_have_a_file_name_defined": 0.0014076280003791908, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_basic_calculation": 0.002350358000057895, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_complex_calculation": 0.0024585389992353157, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_component_frontend_node": 0.0035748250002143322, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_component_versions[1.0.19]": 0.0018996869998773036, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_component_versions[1.1.0]": 0.0013739450000684883, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_component_versions[1.1.1]": 0.001354328999241261, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_division_by_zero": 0.002341380999496323, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_invalid_expression": 0.0022981310003160615, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_latest_version": 0.006072908000533062, - "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_unsupported_operation": 0.002335057999516721, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_all_versions_have_a_file_name_defined": 0.0006243620000532246, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_basic_calculation": 0.0007717370000364099, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_complex_calculation": 0.0008534790000567227, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_component_frontend_node": 0.0020608870000842217, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_component_versions[1.0.19]": 0.0006246539999210654, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_component_versions[1.1.0]": 0.0006095850001202052, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_component_versions[1.1.1]": 0.000589127000012013, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_division_by_zero": 0.0007522410001001845, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_invalid_expression": 0.0007374040001195681, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_latest_version": 0.003058185000099911, + "src/backend/tests/unit/components/tools/test_calculator.py::TestCalculatorComponent::test_unsupported_operation": 0.0007252110000308676, "src/backend/tests/unit/components/tools/test_google_search_api.py::TestGoogleSearchAPICore::test_all_versions_have_a_file_name_defined": 0.0013710770001580386, "src/backend/tests/unit/components/tools/test_google_search_api.py::TestGoogleSearchAPICore::test_build_method": 0.0027305020003041136, "src/backend/tests/unit/components/tools/test_google_search_api.py::TestGoogleSearchAPICore::test_component_initialization": 0.005256973000086873, @@ -955,18 +1035,18 @@ "src/backend/tests/unit/components/tools/test_mcp_component.py::TestMCPToolsComponent::test_validate_connection_params_invalid_mode": 0.0037146149998079636, "src/backend/tests/unit/components/tools/test_mcp_component.py::TestMCPToolsComponent::test_validate_connection_params_missing_command": 0.0031783039994479623, "src/backend/tests/unit/components/tools/test_mcp_component.py::TestMCPToolsComponent::test_validate_connection_params_missing_url": 0.003544085000157793, - "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_all_versions_have_a_file_name_defined": 0.0014874359999339504, - "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_component_initialization": 0.0063500350001959305, - "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_component_versions[1.0.19]": 0.0015697310000177822, - "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_component_versions[1.1.0]": 0.001454223999644455, - "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_component_versions[1.1.1]": 0.0014437649997489643, - "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_latest_version": 0.006059963000097923, + "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_all_versions_have_a_file_name_defined": 0.0006011090000583863, + "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_component_initialization": 0.0021415280000383063, + "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_component_versions[1.0.19]": 0.0006282699999928809, + "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_component_versions[1.1.0]": 0.0006256849999317637, + "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_component_versions[1.1.1]": 0.0006079120000777039, + "src/backend/tests/unit/components/tools/test_python_repl_tool.py::TestPythonREPLComponent::test_latest_version": 0.0026827359999970213, "src/backend/tests/unit/components/tools/test_python_repl_tool.py::test_python_repl_tool_template": 0.02093030200001067, - "src/backend/tests/unit/components/tools/test_serp_api.py::test_error_handling": 0.003194462999999814, - "src/backend/tests/unit/components/tools/test_serp_api.py::test_fetch_content": 0.003285332999894308, - "src/backend/tests/unit/components/tools/test_serp_api.py::test_fetch_content_text": 0.003002384999945207, - "src/backend/tests/unit/components/tools/test_serp_api.py::test_serpapi_initialization": 0.00296008800069103, - "src/backend/tests/unit/components/tools/test_serp_api.py::test_serpapi_template": 0.027727616999982274, + "src/backend/tests/unit/components/tools/test_serp_api.py::test_error_handling": 0.0009478639999542793, + "src/backend/tests/unit/components/tools/test_serp_api.py::test_fetch_content": 0.0010256100000560764, + "src/backend/tests/unit/components/tools/test_serp_api.py::test_fetch_content_text": 0.000859640999919975, + "src/backend/tests/unit/components/tools/test_serp_api.py::test_serpapi_initialization": 0.0006897350001509039, + "src/backend/tests/unit/components/tools/test_serp_api.py::test_serpapi_template": 0.011996560000056888, "src/backend/tests/unit/components/tools/test_wikidata_api.py::TestWikidataComponent::test_all_versions_have_a_file_name_defined": 0.0014399039998806984, "src/backend/tests/unit/components/tools/test_wikidata_api.py::TestWikidataComponent::test_component_versions[1.0.19]": 0.0014149389999147388, "src/backend/tests/unit/components/tools/test_wikidata_api.py::TestWikidataComponent::test_component_versions[1.1.0]": 0.0013904029999594059, @@ -1005,616 +1085,616 @@ "src/backend/tests/unit/components/tools/test_yfinance_tool.py::TestYfinanceComponent::test_initialization": 0.0025505469998279295, "src/backend/tests/unit/components/tools/test_yfinance_tool.py::TestYfinanceComponent::test_template_structure": 0.06717140499995367, "src/backend/tests/unit/components/tools/test_yfinance_tool.py::test_yfinance_tool_template": 0.03864965400003939, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_all_versions_have_a_file_name_defined": 0.04777367899987439, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_chroma_collection_to_data": 0.37519125500011796, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_chroma_collection_to_data_empty_collection": 0.12846856499982096, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_chroma_collection_to_data_without_metadata": 0.39319728600003145, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_component_versions[1.0.19]": 0.48721916699923895, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_component_versions[1.1.0]": 0.19111138900052538, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_component_versions[1.1.1]": 0.17000948999975662, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_create_collection_with_data": 0.5597441840004649, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_create_db": 0.13322291000031328, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_duplicate_handling": 0.694264681000277, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_latest_version": 0.05375235299970882, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_mmr_search": 2.8223301560001346, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_search_with_different_types": 1.1526338419998865, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_search_with_score": 1.2668285809995723, - "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_similarity_search": 1.6043042969999988, - "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_all_versions_have_a_file_name_defined": 0.0015769410006214457, - "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_component_versions[1.0.19]": 0.003839345999494981, - "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_component_versions[1.1.0]": 0.0014891790001456684, - "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_component_versions[1.1.1]": 0.0014682299997730297, - "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_graphrag": 0.013475016999564104, - "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_latest_version": 0.006286812999405811, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_all_versions_have_a_file_name_defined": 0.053008680999937496, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_build_config_update": 0.05065873499961526, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_component_versions[1.0.19]": 0.04946502799930386, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_component_versions[1.1.0]": 0.07349436000049536, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_component_versions[1.1.1]": 0.04929736399935791, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_create_db": 0.12964454299981298, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_create_db_with_data": 0.11887542700014819, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_default_persist_dir": 0.050703850999980205, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_duplicate_handling": 0.4397368409995579, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_latest_version": 0.05470382600015, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_list_existing_collections": 0.04991258900008688, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_mmr_search": 0.31097864799949093, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_search_with_different_types": 0.3581232940005066, - "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_similarity_search": 0.476972599000419, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_all_versions_have_a_file_name_defined": 0.00026104700009454973, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_component_versions[1.0.19]": 0.00026248999984090915, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_component_versions[1.1.0]": 0.00026088599997819983, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_component_versions[1.1.1]": 0.00028399100028764224, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_create_collection_with_data": 0.0002620809996187745, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_create_db": 0.00028727699964292697, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_empty_search_query": 0.00026021699977718526, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_error_handling": 0.0002733020000960096, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_latest_version": 0.0003048690005016397, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_metadata_handling": 0.0006910609999977169, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_mtls_configuration": 0.000284601999737788, - "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_similarity_search": 0.00026387299976704526, - "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_files_independence": 0.0031670260004830197, - "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_input_value_independence": 0.0038019320004423207, - "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_message_output_independence": 0.00475806799977363, - "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_multiple_attributes_independence": 0.0031974929997886647, - "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_sender_name_independence": 0.0031634609995307983, - "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_status_independence": 0.004371787999389198, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_all_versions_have_a_file_name_defined": 0.03937077499995212, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_chroma_collection_to_data": 0.3982903940001279, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_chroma_collection_to_data_empty_collection": 0.11284852199992201, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_chroma_collection_to_data_without_metadata": 0.40461117100005595, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_component_versions[1.0.19]": 0.3838587870000083, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_component_versions[1.1.0]": 0.1596803039998349, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_component_versions[1.1.1]": 0.16709515799993824, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_create_collection_with_data": 0.5303806419999546, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_create_db": 0.13447090300007858, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_duplicate_handling": 0.4981907049999563, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_latest_version": 0.04295910600001207, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_mmr_search": 1.1213709439999775, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_search_with_different_types": 1.451412796999989, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_search_with_score": 1.36208053200005, + "src/backend/tests/unit/components/vectorstores/test_chroma_vector_store_component.py::TestChromaVectorStoreComponent::test_similarity_search": 1.4117057370001476, + "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_all_versions_have_a_file_name_defined": 0.000704982000002019, + "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_component_versions[1.0.19]": 0.000693220000130168, + "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_component_versions[1.1.0]": 0.0006665620001058414, + "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_component_versions[1.1.1]": 0.0006762289999642235, + "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_graphrag": 0.011758406000012656, + "src/backend/tests/unit/components/vectorstores/test_graph_rag_component.py::TestGraphRAGComponent::test_latest_version": 0.00330622499996025, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_all_versions_have_a_file_name_defined": 0.0414289610000651, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_build_config_update": 0.043380645999945955, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_component_versions[1.0.19]": 0.04148047700005009, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_component_versions[1.1.0]": 0.04311537199998838, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_component_versions[1.1.1]": 0.03983998200010319, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_create_db": 0.12161535399991408, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_create_db_with_data": 0.129923510000026, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_default_persist_dir": 0.04194006400007311, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_duplicate_handling": 0.3265917129999707, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_latest_version": 0.04308438400005343, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_list_existing_collections": 0.04010094800003117, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_mmr_search": 1.5184393029998091, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_search_with_different_types": 0.27823831199998494, + "src/backend/tests/unit/components/vectorstores/test_local_db_component.py::TestLocalDBComponent::test_similarity_search": 0.42452174499999273, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_all_versions_have_a_file_name_defined": 0.0002151219999859677, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_component_versions[1.0.19]": 0.00019659600002341904, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_component_versions[1.1.0]": 0.00019923200011362496, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_component_versions[1.1.1]": 0.00019883099992057396, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_create_collection_with_data": 0.00019466300000203773, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_create_db": 0.0001973080001107519, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_empty_search_query": 0.00018888199997491029, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_error_handling": 0.00019639599997844925, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_latest_version": 0.00021391699999639968, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_metadata_handling": 0.00022012900001300295, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_mtls_configuration": 0.00019192699994619034, + "src/backend/tests/unit/components/vectorstores/test_mongodb_atlas.py::TestMongoVectorStoreComponent::test_similarity_search": 0.0001948719999518289, + "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_files_independence": 0.0010059539998792388, + "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_input_value_independence": 0.0030583860000206187, + "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_message_output_independence": 0.0019990929999949003, + "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_multiple_attributes_independence": 0.0010773060000701662, + "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_sender_name_independence": 0.001035679000096934, + "src/backend/tests/unit/custom/component/test_component_instance_attributes.py::test_status_independence": 0.0018043700000589524, "src/backend/tests/unit/custom/component/test_component_to_tool.py::test_component_to_tool": 0.019733334018383175, "src/backend/tests/unit/custom/component/test_component_to_tool.py::test_component_to_tool_has_no_component_as_tool": 0.0017144169833045453, - "src/backend/tests/unit/custom/component/test_component_to_tool.py::test_component_to_toolkit": 0.005888630999379529, - "src/backend/tests/unit/custom/component/test_componet_set_functionality.py::test_set_with_message_text_input_list": 0.0014954240000406571, - "src/backend/tests/unit/custom/component/test_componet_set_functionality.py::test_set_with_mixed_list_input": 0.001645955000185495, - "src/backend/tests/unit/custom/custom_component/test_component.py::test_set_component": 0.003095793999364105, - "src/backend/tests/unit/custom/custom_component/test_component.py::test_set_invalid_output": 0.0038984519997029565, + "src/backend/tests/unit/custom/component/test_component_to_tool.py::test_component_to_toolkit": 0.0030103660001259414, + "src/backend/tests/unit/custom/component/test_componet_set_functionality.py::test_set_with_message_text_input_list": 0.0006414240000367499, + "src/backend/tests/unit/custom/component/test_componet_set_functionality.py::test_set_with_mixed_list_input": 0.0008618859999387496, + "src/backend/tests/unit/custom/custom_component/test_component.py::test_set_component": 0.000925313000038841, + "src/backend/tests/unit/custom/custom_component/test_component.py::test_set_invalid_output": 0.0012319239999669662, "src/backend/tests/unit/custom/custom_component/test_component.py::test_set_required_inputs": 0.0019985559999895486, "src/backend/tests/unit/custom/custom_component/test_component.py::test_set_required_inputs_various_components": 0.006992995000018709, - "src/backend/tests/unit/custom/custom_component/test_component.py::test_update_component_build_config_async": 0.01912224099987725, - "src/backend/tests/unit/custom/custom_component/test_component.py::test_update_component_build_config_sync": 0.047646939000514976, - "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_build_results": 7.697425465999913, - "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_error_handling": 7.380083232999368, - "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_logging": 7.918327265999778, - "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_message_sending": 7.5011763160000555, - "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_streaming_message": 9.683332545000212, - "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_tool_output": 7.609723444999872, - "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_custom_update": 0.0019863279994751792, - "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_invalid_output": 0.0022849459996905352, - "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_output_validation": 0.0021416479999061266, - "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_tool_mode": 0.03224583999963215, - "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_with_existing_tool_output": 0.0021019139999225445, - "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_with_multiple_outputs": 0.002013749000070675, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_accessing_non_registered_callback": 0.0013265349998619058, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_accessing_non_registered_event_callback_with_recommended_fix": 0.001252809999641613, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_accessing_registered_event_callback": 0.0012917099993501324, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_event_id_uniqueness_with_await": 0.0017252409998036455, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_handling_large_number_of_events": 0.0023355700000138313, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_performance_impact_frequent_registrations": 0.002563413999723707, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_queue_receives_correct_event_data_format": 0.0016850249999151856, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_register_event_with_empty_name": 0.0013451919999170059, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_register_event_with_invalid_name_fixed": 0.0014004449999447388, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_register_event_with_valid_name_and_callback_with_mock_callback": 0.001588173999607534, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_register_event_with_valid_name_and_no_callback": 0.0012619250001080218, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_register_event_without_event_type_argument_fixed": 0.0013847360000909248, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_sending_event_with_complex_data": 0.0017743930006872688, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_sending_event_with_none_data": 0.0012808310002583312, + "src/backend/tests/unit/custom/custom_component/test_component.py::test_update_component_build_config_async": 0.0008786759999566129, + "src/backend/tests/unit/custom/custom_component/test_component.py::test_update_component_build_config_sync": 0.001220052000007854, + "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_build_results": 1.3871418210000002, + "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_error_handling": 1.358572337000055, + "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_logging": 1.3366500099999712, + "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_message_sending": 1.370423211000002, + "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_streaming_message": 1.3339441630000692, + "src/backend/tests/unit/custom/custom_component/test_component_events.py::test_component_tool_output": 1.3375308610000047, + "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_custom_update": 0.0009665110000014465, + "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_invalid_output": 0.001052953999874262, + "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_output_validation": 0.00112752300003649, + "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_tool_mode": 0.001518240999871523, + "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_with_existing_tool_output": 0.0009620340000537908, + "src/backend/tests/unit/custom/custom_component/test_update_outputs.py::TestComponentOutputs::test_run_and_validate_update_outputs_with_multiple_outputs": 0.0009890629999063094, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_accessing_non_registered_callback": 0.0005172550000906995, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_accessing_non_registered_event_callback_with_recommended_fix": 0.0005011139999169245, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_accessing_registered_event_callback": 0.0004817980000098032, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_event_id_uniqueness_with_await": 0.0008259009999846967, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_handling_large_number_of_events": 0.001142880000088553, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_performance_impact_frequent_registrations": 0.001056669999911719, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_queue_receives_correct_event_data_format": 0.0008301679998794498, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_register_event_with_empty_name": 0.0005876650001255257, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_register_event_with_invalid_name_fixed": 0.0005772749999550797, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_register_event_with_valid_name_and_callback_with_mock_callback": 0.0007518009999785136, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_register_event_with_valid_name_and_no_callback": 0.0005127460000267092, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_register_event_without_event_type_argument_fixed": 0.0005975249999892185, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_sending_event_with_complex_data": 0.0008124050000333227, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_sending_event_with_none_data": 0.0005058320000443928, "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_sending_event_with_valid_type_and_data_asyncio_plugin": 0.007096707937307656, - "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_thread_safety_accessing_events_dictionary": 0.001638648000152898, - "src/backend/tests/unit/exceptions/test_api.py::test_api_exception": 0.004668605000460957, - "src/backend/tests/unit/exceptions/test_api.py::test_api_exception_no_flow": 0.0012615159998858871, - "src/backend/tests/unit/graph/edge/test_edge_base.py::test_edge_raises_error_on_invalid_target_handle": 0.03613370799985205, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_model_and_assign_values_fails": 0.004569661000004999, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_model_with_fields_from_kwargs": 0.0017348189999211172, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_model_with_invalid_callable": 0.001281441999708477, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_model_with_valid_return_type_annotations": 0.006252512000173738, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_with_multiple_components": 0.006048809999811056, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_with_pydantic_field": 0.004614593999576755, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_default_model_name_to_state": 0.0017177969998556364, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_graph_functional_start_state_update": 7.445465541999965, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_handle_empty_kwargs_gracefully": 0.0015175129997260228, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_raise_typeerror_for_invalid_field_type_in_tuple": 0.001292493999699218, + "src/backend/tests/unit/events/test_event_manager.py::TestEventManager::test_thread_safety_accessing_events_dictionary": 0.0008138880000387871, + "src/backend/tests/unit/exceptions/test_api.py::test_api_exception": 0.0026937850000194885, + "src/backend/tests/unit/exceptions/test_api.py::test_api_exception_no_flow": 0.0005397559999664736, + "src/backend/tests/unit/graph/edge/test_edge_base.py::test_edge_raises_error_on_invalid_target_handle": 0.02435346499987645, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_model_and_assign_values_fails": 0.0029739460001110274, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_model_with_fields_from_kwargs": 0.0009129339999844888, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_model_with_invalid_callable": 0.0006047279998711019, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_model_with_valid_return_type_annotations": 0.0032570560000522164, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_with_multiple_components": 0.002810860999943543, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_create_with_pydantic_field": 0.0031522799999947893, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_default_model_name_to_state": 0.0009406460000036532, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_graph_functional_start_state_update": 1.3799038420000898, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_handle_empty_kwargs_gracefully": 0.0007345390000637053, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_raise_typeerror_for_invalid_field_type_in_tuple": 0.000610148999953708, "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_raise_valueerror_for_invalid_field_type_in_tuple": 0.00342700001783669, - "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_raise_valueerror_for_unsupported_value_types": 0.0012907899995298067, - "src/backend/tests/unit/graph/graph/test_base.py::test_graph": 0.020928279000145267, - "src/backend/tests/unit/graph/graph/test_base.py::test_graph_functional": 0.01950038500035589, - "src/backend/tests/unit/graph/graph/test_base.py::test_graph_functional_async_start": 0.020784882999578258, - "src/backend/tests/unit/graph/graph/test_base.py::test_graph_functional_start": 0.01935189799996806, - "src/backend/tests/unit/graph/graph/test_base.py::test_graph_functional_start_end": 0.03159123200020986, - "src/backend/tests/unit/graph/graph/test_base.py::test_graph_not_prepared": 0.023526218999904813, + "src/backend/tests/unit/graph/graph/state/test_state_model.py::TestCreateStateModel::test_raise_valueerror_for_unsupported_value_types": 0.0006036660000745542, + "src/backend/tests/unit/graph/graph/test_base.py::test_graph": 0.015000994000160972, + "src/backend/tests/unit/graph/graph/test_base.py::test_graph_functional": 0.011718683000140118, + "src/backend/tests/unit/graph/graph/test_base.py::test_graph_functional_async_start": 0.012419909999948686, + "src/backend/tests/unit/graph/graph/test_base.py::test_graph_functional_start": 0.013011415999926612, + "src/backend/tests/unit/graph/graph/test_base.py::test_graph_functional_start_end": 0.022470421999969403, + "src/backend/tests/unit/graph/graph/test_base.py::test_graph_not_prepared": 0.014251483999942138, "src/backend/tests/unit/graph/graph/test_base.py::test_graph_set_with_invalid_component": 0.0009155830484814942, - "src/backend/tests/unit/graph/graph/test_base.py::test_graph_set_with_valid_component": 0.0002657269997143885, - "src/backend/tests/unit/graph/graph/test_base.py::test_graph_with_edge": 0.0192119069997716, - "src/backend/tests/unit/graph/graph/test_callback_graph.py::test_callback_graph": 0.0002493049996701302, - "src/backend/tests/unit/graph/graph/test_cycles.py::test_conditional_router_max_iterations": 0.03171202500016079, - "src/backend/tests/unit/graph/graph/test_cycles.py::test_cycle_in_graph": 0.00026751899986265926, - "src/backend/tests/unit/graph/graph/test_cycles.py::test_cycle_in_graph_max_iterations": 0.02873244700003852, - "src/backend/tests/unit/graph/graph/test_cycles.py::test_that_outputs_cache_is_set_to_false_in_cycle": 0.025659319999704167, - "src/backend/tests/unit/graph/graph/test_cycles.py::test_updated_graph_with_max_iterations": 0.0002737719996730448, - "src/backend/tests/unit/graph/graph/test_cycles.py::test_updated_graph_with_prompts": 0.00028593500019269413, - "src/backend/tests/unit/graph/graph/test_graph_state_model.py::test_graph_functional_start_graph_state_update": 0.028886875999887707, - "src/backend/tests/unit/graph/graph/test_graph_state_model.py::test_graph_state_model": 0.06758599200020399, - "src/backend/tests/unit/graph/graph/test_graph_state_model.py::test_graph_state_model_json_schema": 0.0002691930003493326, - "src/backend/tests/unit/graph/graph/test_graph_state_model.py::test_graph_state_model_serialization": 0.027804824999748234, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_add_to_vertices_being_run": 0.0013039439995736757, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_are_all_predecessors_fulfilled": 0.0012262790000932, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_are_all_predecessors_fulfilled__wrong": 0.0012295050000830088, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_build_run_map": 0.0012445329994079657, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_from_dict": 0.0011768480003411241, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_from_dict_without_run_map__bad_case": 0.0012109409994991438, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_from_dict_without_run_predecessors__bad_case": 0.0011790610001298774, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_from_dict_without_vertices_being_run__bad_case": 0.0011809050001829746, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_from_dict_without_vertices_to_run__bad_case": 0.001215910000155418, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_is_vertex_runnable": 0.0014669580000372662, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_is_vertex_runnable__wrong_is_active": 0.0015827540000827867, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_is_vertex_runnable__wrong_run_predecessors": 0.0012594410000019707, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_is_vertex_runnable__wrong_vertices_to_run": 0.0012874119993284694, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_pickle": 0.001204107999910775, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_remove_from_predecessors": 0.0012771749998137238, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_remove_vertex_from_runnables": 0.001267606000055821, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_to_dict": 0.0012596910000866046, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_update_run_state": 0.0017301900002166803, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_update_vertex_run_state": 0.0012243349997334008, - "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_update_vertex_run_state__bad_case": 0.001216991000546841, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_detects_cycles_in_simple_graph": 0.0011236780001127045, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_disconnected_components": 0.0011026079996554472, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_duplicate_edges": 0.0011273629997958778, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_identifies_multiple_cycles": 0.0011068069998145802, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_large_graphs_efficiency": 0.0020005139999739185, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_mixed_data_types_in_edges": 0.0011657659997581504, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_multiple_edges_between_same_nodes": 0.0011026290003428585, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_no_cycles_present": 0.0011362200002622558, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_nodes_with_no_incoming_edges": 0.0011337060000187194, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_nodes_with_no_outgoing_edges": 0.0011108630001217534, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_self_loops": 0.001132283000060852, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_single_node_no_edges": 0.001113499999519263, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_detects_cycle_in_simple_graph": 0.0012048280000271916, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_disconnected_components": 0.0012069729996255774, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_duplicate_edges": 0.0011506480000207375, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_empty_edges_list": 0.0011349380006322463, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_identifies_first_cycle": 0.0011959419998675003, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_large_graph_efficiency": 0.0011422110001149122, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_multiple_cycles": 0.0011341160002302786, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_multiple_edges_between_same_nodes": 0.0012119820003135828, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_nodes_with_no_outgoing_edges": 0.0011222940001971438, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_returns_none_when_no_cycle": 0.0012369679998300853, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_self_loop_cycle": 0.001100984000004246, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_single_node_no_edges": 0.0011167150000801485, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_correctly_identify_and_return_vertices_in_single_cycle": 0.0011691530003190564, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_detect_cycles_simple_graph": 0.0012128540006415278, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_duplicate_edges_fixed_fixed": 0.0012133249997532403, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_empty_edges": 0.0011466410001048644, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_large_graphs_efficiently": 0.0011902630003532977, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_no_outgoing_edges": 0.0011706449995472212, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_self_loops": 0.001222822000272572, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_single_cycle": 0.0011639209997156286, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_two_inputs_in_cycle[0]": 0.0012152589997640462, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_two_inputs_in_cycle[1]": 0.0011983580006926786, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_two_inputs_in_cycle[2]": 0.001222593000420602, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_two_inputs_in_cycle[3]": 0.0012359269994703936, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_two_inputs_in_cycle[4]": 0.0012158700001236866, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_no_cycles_empty_list": 0.0011724179998964246, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_no_modification_of_input_edges_list": 0.0012195359995530453, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_non_string_vertex_ids": 0.0011843600004795007, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_process_disconnected_components": 0.0012128729995311005, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_return_vertices_involved_in_multiple_cycles": 0.0012154189998909715, - "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_single_vertex_no_edges": 0.001164362999588775, - "src/backend/tests/unit/graph/graph/test_utils.py::test_chat_inputs_at_start": 0.001222022000092693, - "src/backend/tests/unit/graph/graph/test_utils.py::test_filter_vertices_from_vertex": 0.0011196099994776887, - "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_exact_sequence": 0.001224094000463083, - "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_simple": 0.0011319829995954933, - "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_with_complex_cycle": 0.0012184139995952137, - "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_with_cycle": 0.001167368000096758, - "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_with_stop": 0.0011387949998606928, - "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_with_stop_at_chroma": 0.0012255179999556276, - "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_with_unconnected_graph": 0.0011451080004007963, - "src/backend/tests/unit/graph/graph/test_utils.py::test_get_successors_a": 0.0012947169998369645, - "src/backend/tests/unit/graph/graph/test_utils.py::test_get_successors_z": 0.001251456000318285, - "src/backend/tests/unit/graph/graph/test_utils.py::test_has_cycle": 0.0011958819995925296, - "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_a": 0.0012516069996308943, - "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_g": 0.0012343329999566777, - "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_h": 0.0012205579996589222, - "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_invalid_vertex": 0.001377190999846789, - "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_m": 0.0012347349997980928, - "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_n_is_start": 0.0013160560001779231, - "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_t": 0.001266583999949944, - "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_x": 0.0012821929999518034, - "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_z": 0.0012860000001637673, + "src/backend/tests/unit/graph/graph/test_base.py::test_graph_set_with_valid_component": 0.0002317110000831235, + "src/backend/tests/unit/graph/graph/test_base.py::test_graph_with_edge": 0.012744304999841916, + "src/backend/tests/unit/graph/graph/test_callback_graph.py::test_callback_graph": 0.00020359999996344413, + "src/backend/tests/unit/graph/graph/test_cycles.py::test_conditional_router_max_iterations": 0.02252257800012103, + "src/backend/tests/unit/graph/graph/test_cycles.py::test_cycle_in_graph": 0.00019843099994432123, + "src/backend/tests/unit/graph/graph/test_cycles.py::test_cycle_in_graph_max_iterations": 0.01983902599999965, + "src/backend/tests/unit/graph/graph/test_cycles.py::test_that_outputs_cache_is_set_to_false_in_cycle": 0.016803654000113966, + "src/backend/tests/unit/graph/graph/test_cycles.py::test_updated_graph_with_max_iterations": 0.00018557699991106347, + "src/backend/tests/unit/graph/graph/test_cycles.py::test_updated_graph_with_prompts": 0.00021510099998067744, + "src/backend/tests/unit/graph/graph/test_graph_state_model.py::test_graph_functional_start_graph_state_update": 0.02027101299984224, + "src/backend/tests/unit/graph/graph/test_graph_state_model.py::test_graph_state_model": 0.05547409800010428, + "src/backend/tests/unit/graph/graph/test_graph_state_model.py::test_graph_state_model_json_schema": 0.00027916000010463904, + "src/backend/tests/unit/graph/graph/test_graph_state_model.py::test_graph_state_model_serialization": 0.019648649000032492, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_add_to_vertices_being_run": 0.00045958800001244526, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_are_all_predecessors_fulfilled": 0.0004516410000405813, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_are_all_predecessors_fulfilled__wrong": 0.0006122220000861489, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_build_run_map": 0.00045089100001405313, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_from_dict": 0.0009307149998676323, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_from_dict_without_run_map__bad_case": 0.000495943999908377, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_from_dict_without_run_predecessors__bad_case": 0.0004922870001564661, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_from_dict_without_vertices_being_run__bad_case": 0.00047558699998262455, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_from_dict_without_vertices_to_run__bad_case": 0.00048778999996557104, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_is_vertex_runnable": 0.0004527549999693292, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_is_vertex_runnable__wrong_is_active": 0.0004485460001433239, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_is_vertex_runnable__wrong_run_predecessors": 0.00048692800010030624, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_is_vertex_runnable__wrong_vertices_to_run": 0.00046896500009552256, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_pickle": 0.0005207110000355897, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_remove_from_predecessors": 0.00045179299991104926, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_remove_vertex_from_runnables": 0.0004443599998467107, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_to_dict": 0.0005362990000321588, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_update_run_state": 0.0005025269998668591, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_update_vertex_run_state": 0.0004646959999945466, + "src/backend/tests/unit/graph/graph/test_runnable_vertices_manager.py::test_update_vertex_run_state__bad_case": 0.00044776499998988584, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_detects_cycles_in_simple_graph": 0.00046070899998085224, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_disconnected_components": 0.0004444489999286816, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_duplicate_edges": 0.0006305759999349903, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_identifies_multiple_cycles": 0.0004273669999292906, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_large_graphs_efficiency": 0.0008405190000075891, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_mixed_data_types_in_edges": 0.00044285599994964286, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_multiple_edges_between_same_nodes": 0.0004377650000151334, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_no_cycles_present": 0.0004144539999515473, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_nodes_with_no_incoming_edges": 0.00042082600009507587, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_nodes_with_no_outgoing_edges": 0.00041730800001005264, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_self_loops": 0.00044144399998913286, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindAllCycleEdges::test_single_node_no_edges": 0.00041392299999643, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_detects_cycle_in_simple_graph": 0.0004300220000459376, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_disconnected_components": 0.00043977000007089373, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_duplicate_edges": 0.000449368999966282, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_empty_edges_list": 0.0004173580000497168, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_identifies_first_cycle": 0.00044486099989171635, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_large_graph_efficiency": 0.0004429069998650448, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_multiple_cycles": 0.0004248310001457867, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_multiple_edges_between_same_nodes": 0.00045056900012241385, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_nodes_with_no_outgoing_edges": 0.0004171690001157913, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_returns_none_when_no_cycle": 0.0004278769999928045, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_self_loop_cycle": 0.0004241520000505261, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleEdge::test_single_node_no_edges": 0.00041808100002072024, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_correctly_identify_and_return_vertices_in_single_cycle": 0.00045146200000090175, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_detect_cycles_simple_graph": 0.0004940510000324139, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_duplicate_edges_fixed_fixed": 0.0005100709997805097, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_empty_edges": 0.0004718710000588544, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_large_graphs_efficiently": 0.0005053309999993871, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_no_outgoing_edges": 0.0004683230000637195, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_self_loops": 0.0004981289999932415, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_single_cycle": 0.0004845340000656506, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_two_inputs_in_cycle[0]": 0.000505381999914789, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_two_inputs_in_cycle[1]": 0.0005069140000841799, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_two_inputs_in_cycle[2]": 0.0004926689999820155, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_two_inputs_in_cycle[3]": 0.00048513400008687313, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_handle_two_inputs_in_cycle[4]": 0.0004935199999636097, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_no_cycles_empty_list": 0.0004586960000096951, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_no_modification_of_input_edges_list": 0.0005124150000028749, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_non_string_vertex_ids": 0.0004644460000235995, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_process_disconnected_components": 0.0004890220000106638, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_return_vertices_involved_in_multiple_cycles": 0.0004708080000455084, + "src/backend/tests/unit/graph/graph/test_utils.py::TestFindCycleVertices::test_single_vertex_no_edges": 0.00043001300002742937, + "src/backend/tests/unit/graph/graph/test_utils.py::test_chat_inputs_at_start": 0.0005212219999748413, + "src/backend/tests/unit/graph/graph/test_utils.py::test_filter_vertices_from_vertex": 0.00043489200004387385, + "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_exact_sequence": 0.0005128870000135066, + "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_simple": 0.0004795840000042517, + "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_with_complex_cycle": 0.0004998829999749432, + "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_with_cycle": 0.0004501499998923464, + "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_with_stop": 0.00043425000012575765, + "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_with_stop_at_chroma": 0.0005198890000883694, + "src/backend/tests/unit/graph/graph/test_utils.py::test_get_sorted_vertices_with_unconnected_graph": 0.00045597900020766247, + "src/backend/tests/unit/graph/graph/test_utils.py::test_get_successors_a": 0.0004608089999464937, + "src/backend/tests/unit/graph/graph/test_utils.py::test_get_successors_z": 0.00044446899994454725, + "src/backend/tests/unit/graph/graph/test_utils.py::test_has_cycle": 0.00044174300012400636, + "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_a": 0.0004842429998461739, + "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_g": 0.0004715099998975347, + "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_h": 0.0004511420002017985, + "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_invalid_vertex": 0.0005704319999040308, + "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_m": 0.0004419740000685124, + "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_n_is_start": 0.0005256289998669672, + "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_t": 0.0004680730000927724, + "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_x": 0.00048442399986470264, + "src/backend/tests/unit/graph/graph/test_utils.py::test_sort_up_to_vertex_z": 0.0004841529998884653, "src/backend/tests/unit/graph/test_graph.py::test_build_edges": 0.001086625037714839, "src/backend/tests/unit/graph/test_graph.py::test_build_nodes": 0.0012113330303691328, "src/backend/tests/unit/graph/test_graph.py::test_build_params": 0.00745550001738593, "src/backend/tests/unit/graph/test_graph.py::test_circular_dependencies": 0.0011518750106915832, - "src/backend/tests/unit/graph/test_graph.py::test_find_last_node": 0.0015255369999067625, + "src/backend/tests/unit/graph/test_graph.py::test_find_last_node": 0.0007918870001049072, "src/backend/tests/unit/graph/test_graph.py::test_get_node": 3.6276886249543168, "src/backend/tests/unit/graph/test_graph.py::test_get_node_neighbors_basic": 0.0015942919999361038, "src/backend/tests/unit/graph/test_graph.py::test_get_root_vertex": 0.00336533400695771, "src/backend/tests/unit/graph/test_graph.py::test_get_vertices_with_target": 0.0015001240535639226, "src/backend/tests/unit/graph/test_graph.py::test_graph_structure": 3.660518125980161, - "src/backend/tests/unit/graph/test_graph.py::test_invalid_node_types": 0.0016769500002737914, + "src/backend/tests/unit/graph/test_graph.py::test_invalid_node_types": 0.0006933410001010998, "src/backend/tests/unit/graph/test_graph.py::test_matched_type": 0.0011828330461867154, "src/backend/tests/unit/graph/test_graph.py::test_pickle_graph": 0.025576499931048602, - "src/backend/tests/unit/graph/test_graph.py::test_process_flow": 0.0024239839999609103, - "src/backend/tests/unit/graph/test_graph.py::test_process_flow_one_group": 0.0028981989999010693, - "src/backend/tests/unit/graph/test_graph.py::test_process_flow_vector_store_grouped": 0.008508529999744496, - "src/backend/tests/unit/graph/test_graph.py::test_serialize_graph": 0.0033941149995371234, - "src/backend/tests/unit/graph/test_graph.py::test_set_new_target_handle": 0.00113402600027257, - "src/backend/tests/unit/graph/test_graph.py::test_ungroup_node": 0.0022333480005727324, - "src/backend/tests/unit/graph/test_graph.py::test_update_source_handle": 0.00117721700007678, - "src/backend/tests/unit/graph/test_graph.py::test_update_target_handle_proxy": 0.0011475920009615947, - "src/backend/tests/unit/graph/test_graph.py::test_update_template": 0.001378181999825756, + "src/backend/tests/unit/graph/test_graph.py::test_process_flow": 0.0015197430000171153, + "src/backend/tests/unit/graph/test_graph.py::test_process_flow_one_group": 0.0018970579999404436, + "src/backend/tests/unit/graph/test_graph.py::test_process_flow_vector_store_grouped": 0.0028809919999730482, + "src/backend/tests/unit/graph/test_graph.py::test_serialize_graph": 0.0018235909999475552, + "src/backend/tests/unit/graph/test_graph.py::test_set_new_target_handle": 0.00045852400000967464, + "src/backend/tests/unit/graph/test_graph.py::test_ungroup_node": 0.0012679660000003423, + "src/backend/tests/unit/graph/test_graph.py::test_update_source_handle": 0.00044685399996069464, + "src/backend/tests/unit/graph/test_graph.py::test_update_target_handle_proxy": 0.00046525699997346237, + "src/backend/tests/unit/graph/test_graph.py::test_update_template": 0.0005869339998980649, "src/backend/tests/unit/graph/test_graph.py::test_validate_edges": 0.0010510420543141663, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_handle_optional_field": 0.002192442000250594, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_edge_parameters": 0.0030681059993185045, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_bool_field": 0.002150606000213884, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_code_error": 0.0023185670002021652, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_dict_field_list": 0.0021789770007671905, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_invalid": 0.002315600999736489, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_table_field": 0.0031482459999097046, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_table_field_invalid": 0.002286667000134912, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_valid": 0.002301765000083833, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_file_field": 0.0022827399998277542, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_non_list_edge_param": 0.002580004999799712, - "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_should_skip_field": 0.002196680999986711, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_correctly_accesses_descriptions_recommended_fix": 0.0021441320000121777, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_create_model_from_valid_schema": 0.0022989009994489606, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_handle_empty_schema": 0.0014589120000891853, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_handle_large_schemas_efficiently": 0.0021526470000026166, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_handles_multiple_fields_fixed_with_instance_check": 0.0026265110000167624, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_manages_unknown_field_types": 0.0013220279997767648, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_nested_list_and_dict_types_handling": 0.0019897040001524147, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_no_duplicate_field_names_fixed_fixed": 0.0017304400003013143, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_process_schema_missing_optional_keys_updated": 0.002281778999531525, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_raises_error_for_invalid_input_different_exception_with_specific_exception": 0.0012078439999640977, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_returns_valid_model_class": 0.0017883579998851928, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_schema_fields_with_none_default": 0.0019412529995861405, - "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_supports_single_and_multiple_type_annotations": 0.0019482660004541685, - "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list[{name} is {age} years old-data0-expected0]": 0.001275370000712428, - "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list[{name} is {age} years old-data1-expected1]": 0.001270631999886973, - "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__data_contains_nested_data_key": 0.0011620189998211572, - "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__data_with_data_attribute_empty": 0.0011149920005664171, - "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__template_empty": 0.0011328040000080364, - "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__template_without_placeholder": 0.0011237070002607652, - "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__template_without_placeholder_and_data_attribute_empty": 0.0011714469997059496, - "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__template_wrong_placeholder": 0.0011218439999538532, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_complex_nested_data": 0.0011096110001744819, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_empty_data_dict": 0.001144977999956609, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_empty_template": 0.00114263099976597, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_invalid_template_type": 0.001206352000735933, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_missing_key": 0.0011001130001204729, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_mixed_data_types": 0.0011451269997451163, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_none_data": 0.0011039709997930913, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_none_template": 0.0012582780000229832, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[Error: {text}-data4-expected_text4]": 0.0012340130001575744, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[Text: {text}-data0-expected_text0]": 0.0012438700000529934, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[User: {text}-data3-expected_text3]": 0.0012395540002216876, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[Value: {text}-data5-expected_text5]": 0.0012231129994688672, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[{name} is {age} years old-data1-expected_text1]": 0.0012235740000505757, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[{name} is {age} years old-data2-expected_text2]": 0.0012195569997857092, - "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_string_data": 0.0011182779999217018, - "src/backend/tests/unit/initial_setup/starter_projects/test_memory_chatbot.py::test_memory_chatbot": 8.061599841000316, - "src/backend/tests/unit/initial_setup/starter_projects/test_memory_chatbot.py::test_memory_chatbot_dump_components_and_edges": 0.03716516500026046, - "src/backend/tests/unit/initial_setup/starter_projects/test_memory_chatbot.py::test_memory_chatbot_dump_structure": 0.042283347999727994, - "src/backend/tests/unit/initial_setup/starter_projects/test_vector_store_rag.py::test_vector_store_rag": 0.21914502800018454, - "src/backend/tests/unit/initial_setup/starter_projects/test_vector_store_rag.py::test_vector_store_rag_add": 0.18251568199957546, - "src/backend/tests/unit/initial_setup/starter_projects/test_vector_store_rag.py::test_vector_store_rag_dump": 0.09710826599985012, - "src/backend/tests/unit/initial_setup/starter_projects/test_vector_store_rag.py::test_vector_store_rag_dump_components_and_edges": 0.09802826099985396, - "src/backend/tests/unit/initial_setup/test_setup_functions.py::test_get_or_create_default_folder_concurrent_calls": 7.460683012999652, - "src/backend/tests/unit/initial_setup/test_setup_functions.py::test_get_or_create_default_folder_creation": 7.501890105999792, - "src/backend/tests/unit/initial_setup/test_setup_functions.py::test_get_or_create_default_folder_idempotency": 7.53592784600005, - "src/backend/tests/unit/inputs/test_inputs.py::test_bool_input_invalid": 0.0012757809995491698, - "src/backend/tests/unit/inputs/test_inputs.py::test_bool_input_valid": 0.0011845019998872885, - "src/backend/tests/unit/inputs/test_inputs.py::test_code_input_valid": 0.0012122319999434694, - "src/backend/tests/unit/inputs/test_inputs.py::test_data_input_valid": 0.0012173330001132854, - "src/backend/tests/unit/inputs/test_inputs.py::test_dict_input_invalid": 0.0011660569998639403, - "src/backend/tests/unit/inputs/test_inputs.py::test_dict_input_valid": 0.0011320749999867985, - "src/backend/tests/unit/inputs/test_inputs.py::test_dropdown_input_invalid": 0.0011631309998847428, - "src/backend/tests/unit/inputs/test_inputs.py::test_dropdown_input_valid": 0.0011429340001996025, - "src/backend/tests/unit/inputs/test_inputs.py::test_file_input_valid": 0.0011195900005986914, - "src/backend/tests/unit/inputs/test_inputs.py::test_float_input_invalid": 0.0012116210000385763, - "src/backend/tests/unit/inputs/test_inputs.py::test_float_input_valid": 0.001210489999721176, - "src/backend/tests/unit/inputs/test_inputs.py::test_handle_input_invalid": 0.001220028999796341, - "src/backend/tests/unit/inputs/test_inputs.py::test_handle_input_valid": 0.0012439330002962379, - "src/backend/tests/unit/inputs/test_inputs.py::test_instantiate_input_comprehensive": 0.0012374099997032317, - "src/backend/tests/unit/inputs/test_inputs.py::test_instantiate_input_invalid": 0.0013268570000946056, - "src/backend/tests/unit/inputs/test_inputs.py::test_instantiate_input_valid": 0.0012309089997870615, - "src/backend/tests/unit/inputs/test_inputs.py::test_int_input_invalid": 0.0012212990000080026, - "src/backend/tests/unit/inputs/test_inputs.py::test_int_input_valid": 0.0012650419998863072, - "src/backend/tests/unit/inputs/test_inputs.py::test_message_text_input_invalid": 0.00132213800043246, - "src/backend/tests/unit/inputs/test_inputs.py::test_message_text_input_valid": 0.0013493789997482963, - "src/backend/tests/unit/inputs/test_inputs.py::test_multiline_input_invalid": 0.0012139969999225286, - "src/backend/tests/unit/inputs/test_inputs.py::test_multiline_input_valid": 0.0012182440000287897, - "src/backend/tests/unit/inputs/test_inputs.py::test_multiline_secret_input_invalid": 0.0013410030001068662, - "src/backend/tests/unit/inputs/test_inputs.py::test_multiline_secret_input_valid": 0.0012355960002423672, - "src/backend/tests/unit/inputs/test_inputs.py::test_multiselect_input_invalid": 0.0011627510002654162, - "src/backend/tests/unit/inputs/test_inputs.py::test_multiselect_input_valid": 0.001167980000445823, - "src/backend/tests/unit/inputs/test_inputs.py::test_nested_dict_input_invalid": 0.0011460499999884632, - "src/backend/tests/unit/inputs/test_inputs.py::test_nested_dict_input_valid": 0.0011584019994188566, - "src/backend/tests/unit/inputs/test_inputs.py::test_prompt_input_valid": 0.0012093459999960032, - "src/backend/tests/unit/inputs/test_inputs.py::test_secret_str_input_invalid": 0.0012084760001016548, - "src/backend/tests/unit/inputs/test_inputs.py::test_secret_str_input_valid": 0.0012378500000522763, - "src/backend/tests/unit/inputs/test_inputs.py::test_slider_input_valid": 0.0012424689994077198, - "src/backend/tests/unit/inputs/test_inputs.py::test_str_input_invalid": 0.0012947679997523664, - "src/backend/tests/unit/inputs/test_inputs.py::test_str_input_valid": 0.0012434719997145294, - "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_invalid[non_string_value-options2-123-TypeError]": 0.0013346219998311426, - "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_invalid[option_too_long-options1-Tab1-ValidationError]": 0.0012809320000997104, - "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_invalid[too_many_options-options0-Tab1-ValidationError]": 0.0012983050000912044, - "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_valid[empty_options-options2--expected_options2-]": 0.0013479750000442436, - "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_valid[fewer_options-options1-Tab2-expected_options1-Tab2]": 0.0013674530000571394, - "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_valid[standard_valid-options0-Tab1-expected_options0-Tab1]": 0.0013563219999923604, - "src/backend/tests/unit/inputs/test_inputs.py::test_table_input_invalid": 0.0012623259999600123, - "src/backend/tests/unit/inputs/test_inputs.py::test_table_input_valid": 0.0016301240002576378, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_complex_nested_structures_handling": 0.001665399000103207, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_default_values_assignment": 0.0016010200006348896, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_default_values_for_non_required_fields": 0.0016279390006275207, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_empty_list_of_inputs": 0.001387489000990172, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_field_types_conversion": 0.0016270290002466936, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_fields_creation_with_correct_types_and_attributes": 0.0016186519997063442, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_handle_optional_field": 0.0011616059999823847, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_edge_parameters": 0.0017276609999044013, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_bool_field": 0.0011531300000342526, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_code_error": 0.001250122000101328, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_dict_field_list": 0.001181883999947786, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_invalid": 0.0012517540000089866, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_table_field": 0.0019786600000770704, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_table_field_invalid": 0.0013070079997987705, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_field_parameters_valid": 0.0012675750000425978, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_file_field": 0.001208884999869042, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_process_non_list_edge_param": 0.0014094570000224849, + "src/backend/tests/unit/graph/vertex/test_vertex_base.py::test_should_skip_field": 0.0012019920001193896, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_correctly_accesses_descriptions_recommended_fix": 0.0011464780000096653, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_create_model_from_valid_schema": 0.0013091519999761658, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_handle_empty_schema": 0.0007111439999789582, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_handle_large_schemas_efficiently": 0.0012034149999635702, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_handles_multiple_fields_fixed_with_instance_check": 0.0011914020001313474, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_manages_unknown_field_types": 0.0005913030000783692, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_nested_list_and_dict_types_handling": 0.0010613179999836575, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_no_duplicate_field_names_fixed_fixed": 0.000912743000071714, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_process_schema_missing_optional_keys_updated": 0.0033996690001458774, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_raises_error_for_invalid_input_different_exception_with_specific_exception": 0.0004976380000698555, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_returns_valid_model_class": 0.0009776430000556502, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_schema_fields_with_none_default": 0.0010549579999405978, + "src/backend/tests/unit/helpers/test_base_model_from_schema.py::TestBuildModelFromSchema::test_supports_single_and_multiple_type_annotations": 0.0010655569999471481, + "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list[{name} is {age} years old-data0-expected0]": 0.0005940199999940887, + "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list[{name} is {age} years old-data1-expected1]": 0.0005784779999657985, + "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__data_contains_nested_data_key": 0.0004661600000872568, + "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__data_with_data_attribute_empty": 0.00046464600006856926, + "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__template_empty": 0.0005061230000364958, + "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__template_without_placeholder": 0.0004744149999851288, + "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__template_without_placeholder_and_data_attribute_empty": 0.00048108599992247036, + "src/backend/tests/unit/helpers/test_data.py::test_data_to_text_list__template_wrong_placeholder": 0.0004875189999893337, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_complex_nested_data": 0.0004921869999634509, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_empty_data_dict": 0.00047547700000905024, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_empty_template": 0.0004611889999068808, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_invalid_template_type": 0.0005234569999856831, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_missing_key": 0.000464286000010361, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_mixed_data_types": 0.0005002829998375091, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_none_data": 0.000460978999967665, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_none_template": 0.0005808629999819459, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[Error: {text}-data4-expected_text4]": 0.0005573300001060488, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[Text: {text}-data0-expected_text0]": 0.0005590130000427962, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[User: {text}-data3-expected_text3]": 0.0005635599999322949, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[Value: {text}-data5-expected_text5]": 0.0005588529999158709, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[{name} is {age} years old-data1-expected_text1]": 0.0005679500001178894, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_parametrized[{name} is {age} years old-data2-expected_text2]": 0.0005707839999331554, + "src/backend/tests/unit/helpers/test_data_to_text_list.py::test_data_to_text_list_string_data": 0.0004560800000490417, + "src/backend/tests/unit/initial_setup/starter_projects/test_memory_chatbot.py::test_memory_chatbot": 1.3265050659999815, + "src/backend/tests/unit/initial_setup/starter_projects/test_memory_chatbot.py::test_memory_chatbot_dump_components_and_edges": 0.02719521199992414, + "src/backend/tests/unit/initial_setup/starter_projects/test_memory_chatbot.py::test_memory_chatbot_dump_structure": 0.031067926999980955, + "src/backend/tests/unit/initial_setup/starter_projects/test_vector_store_rag.py::test_vector_store_rag": 0.16861074400003417, + "src/backend/tests/unit/initial_setup/starter_projects/test_vector_store_rag.py::test_vector_store_rag_add": 0.12601884099990457, + "src/backend/tests/unit/initial_setup/starter_projects/test_vector_store_rag.py::test_vector_store_rag_dump": 0.06443047100003696, + "src/backend/tests/unit/initial_setup/starter_projects/test_vector_store_rag.py::test_vector_store_rag_dump_components_and_edges": 0.06755089999990105, + "src/backend/tests/unit/initial_setup/test_setup_functions.py::test_get_or_create_default_folder_concurrent_calls": 1.3576264420000825, + "src/backend/tests/unit/initial_setup/test_setup_functions.py::test_get_or_create_default_folder_creation": 1.329168482, + "src/backend/tests/unit/initial_setup/test_setup_functions.py::test_get_or_create_default_folder_idempotency": 1.323012932000097, + "src/backend/tests/unit/inputs/test_inputs.py::test_bool_input_invalid": 0.0004312119998530761, + "src/backend/tests/unit/inputs/test_inputs.py::test_bool_input_valid": 0.000472439999953167, + "src/backend/tests/unit/inputs/test_inputs.py::test_code_input_valid": 0.00046006600007331144, + "src/backend/tests/unit/inputs/test_inputs.py::test_data_input_valid": 0.0004334669999934704, + "src/backend/tests/unit/inputs/test_inputs.py::test_dict_input_invalid": 0.0004302809999217061, + "src/backend/tests/unit/inputs/test_inputs.py::test_dict_input_valid": 0.00042891000009603886, + "src/backend/tests/unit/inputs/test_inputs.py::test_dropdown_input_invalid": 0.0004510210000034931, + "src/backend/tests/unit/inputs/test_inputs.py::test_dropdown_input_valid": 0.0004292599999189406, + "src/backend/tests/unit/inputs/test_inputs.py::test_file_input_valid": 0.00042810800005099736, + "src/backend/tests/unit/inputs/test_inputs.py::test_float_input_invalid": 0.00047733999997490173, + "src/backend/tests/unit/inputs/test_inputs.py::test_float_input_valid": 0.0004526420000274811, + "src/backend/tests/unit/inputs/test_inputs.py::test_handle_input_invalid": 0.000430511999979899, + "src/backend/tests/unit/inputs/test_inputs.py::test_handle_input_valid": 0.00043601300012596766, + "src/backend/tests/unit/inputs/test_inputs.py::test_instantiate_input_comprehensive": 0.0005157299999609677, + "src/backend/tests/unit/inputs/test_inputs.py::test_instantiate_input_invalid": 0.00054930399994646, + "src/backend/tests/unit/inputs/test_inputs.py::test_instantiate_input_valid": 0.0004577019999487675, + "src/backend/tests/unit/inputs/test_inputs.py::test_int_input_invalid": 0.0004394180000417691, + "src/backend/tests/unit/inputs/test_inputs.py::test_int_input_valid": 0.00046902199994747207, + "src/backend/tests/unit/inputs/test_inputs.py::test_message_text_input_invalid": 0.0004943100000218692, + "src/backend/tests/unit/inputs/test_inputs.py::test_message_text_input_valid": 0.0005463879998615084, + "src/backend/tests/unit/inputs/test_inputs.py::test_multiline_input_invalid": 0.00045324400002755283, + "src/backend/tests/unit/inputs/test_inputs.py::test_multiline_input_valid": 0.0004806349999171289, + "src/backend/tests/unit/inputs/test_inputs.py::test_multiline_secret_input_invalid": 0.0004698650001273563, + "src/backend/tests/unit/inputs/test_inputs.py::test_multiline_secret_input_valid": 0.00044861599997148005, + "src/backend/tests/unit/inputs/test_inputs.py::test_multiselect_input_invalid": 0.0004566600001680854, + "src/backend/tests/unit/inputs/test_inputs.py::test_multiselect_input_valid": 0.0004854029998568876, + "src/backend/tests/unit/inputs/test_inputs.py::test_nested_dict_input_invalid": 0.00045804399996995926, + "src/backend/tests/unit/inputs/test_inputs.py::test_nested_dict_input_valid": 0.00043481900002007023, + "src/backend/tests/unit/inputs/test_inputs.py::test_prompt_input_valid": 0.00044667200006642815, + "src/backend/tests/unit/inputs/test_inputs.py::test_secret_str_input_invalid": 0.0004616199998963566, + "src/backend/tests/unit/inputs/test_inputs.py::test_secret_str_input_valid": 0.0004605280001896972, + "src/backend/tests/unit/inputs/test_inputs.py::test_slider_input_valid": 0.0004653059999100151, + "src/backend/tests/unit/inputs/test_inputs.py::test_str_input_invalid": 0.00048505299992029904, + "src/backend/tests/unit/inputs/test_inputs.py::test_str_input_valid": 0.00047011599986035435, + "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_invalid[non_string_value-options2-123-TypeError]": 0.0005339460000186591, + "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_invalid[option_too_long-options1-Tab1-ValidationError]": 0.0005569179999156404, + "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_invalid[too_many_options-options0-Tab1-ValidationError]": 0.0005559459999631144, + "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_valid[empty_options-options2--expected_options2-]": 0.0005604250000033062, + "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_valid[fewer_options-options1-Tab2-expected_options1-Tab2]": 0.0005549829999154099, + "src/backend/tests/unit/inputs/test_inputs.py::test_tab_input_valid[standard_valid-options0-Tab1-expected_options0-Tab1]": 0.0005510370000365583, + "src/backend/tests/unit/inputs/test_inputs.py::test_table_input_invalid": 0.0005156800000349904, + "src/backend/tests/unit/inputs/test_inputs.py::test_table_input_valid": 0.0007672289999618442, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_complex_nested_structures_handling": 0.0008445629999869197, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_default_values_assignment": 0.000808625999979995, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_default_values_for_non_required_fields": 0.0007833390000087093, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_empty_list_of_inputs": 0.0006596990000389269, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_field_types_conversion": 0.0007961929998145933, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_fields_creation_with_correct_types_and_attributes": 0.000807954999913818, "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_invalid_field_types_handling": 0.0005195839912630618, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_is_list_attribute_processing": 0.0016960570001174347, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_is_list_handling": 0.0017007339993142523, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_missing_attributes_handling": 0.0016328490000887541, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_missing_optional_attributes": 0.0019113779999315739, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_mixed_required_optional_fields_processing": 0.0017277160000048752, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_multiple_input_types": 0.0017791620002753916, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_non_standard_field_types_handling": 0.0016153649994521402, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_none_default_value_handling": 0.001661329999933514, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_options_attribute_processing": 0.0017756340002961224, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_options_handling": 0.001731331999963004, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_passing_input_type_directly": 0.0011433149998083536, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_schema_model_creation": 0.0016462329995192704, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_single_input_type_conversion": 0.0016692159997546696, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_single_input_type_replica": 0.001621808000436431, - "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_special_characters_in_names_handling": 0.001649910999731219, - "src/backend/tests/unit/io/test_io_schema.py::test_create_input_schema": 0.0031696669998382276, - "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_create_column_with_valid_formatter": 0.0011957739998251782, - "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_create_column_without_display_name": 0.0011934899998777837, - "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_create_with_type_instead_of_formatter": 0.0011828870001409086, - "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_default_sortable_filterable": 0.0011385050001990749, - "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_description_and_default": 0.0011695819998749357, - "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_formatter_explicitly_set_to_enum": 0.00115106899966122, - "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_formatter_none_when_not_provided": 0.001155827000275167, - "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_formatter_set_based_on_value": 0.0011664980002024095, - "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_invalid_formatter_raises_value_error": 0.0013097849996484001, - "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_allow_markdown_override": 0.001126354000007268, - "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_initialize_with_empty_contents": 0.0011477219995867927, - "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_initialize_with_valid_title_and_contents": 0.0014135189994703978, - "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_invalid_contents_type": 0.0012647509997805173, - "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_media_url_handling": 0.001150769000105356, - "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_serialize_contents": 0.0012456849995032826, - "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_single_content_conversion": 0.0011648549993878987, - "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_validate_different_content_types": 0.0015780859998812957, - "src/backend/tests/unit/schema/test_content_types.py::TestBaseContent::test_base_content_serialization": 0.0011911930000678694, - "src/backend/tests/unit/schema/test_content_types.py::TestBaseContent::test_base_content_with_duration": 0.001143463999596861, - "src/backend/tests/unit/schema/test_content_types.py::TestBaseContent::test_base_content_with_header": 0.0011612270004661696, - "src/backend/tests/unit/schema/test_content_types.py::TestCodeContent::test_code_content_creation": 0.0011407389997657447, - "src/backend/tests/unit/schema/test_content_types.py::TestCodeContent::test_code_content_without_title": 0.001139498000156891, - "src/backend/tests/unit/schema/test_content_types.py::TestErrorContent::test_error_content_creation": 0.0011245789996792155, - "src/backend/tests/unit/schema/test_content_types.py::TestErrorContent::test_error_content_optional_fields": 0.0011609060002228944, - "src/backend/tests/unit/schema/test_content_types.py::TestJSONContent::test_json_content_complex_data": 0.0011598759997468733, - "src/backend/tests/unit/schema/test_content_types.py::TestJSONContent::test_json_content_creation": 0.0011531230006767146, - "src/backend/tests/unit/schema/test_content_types.py::TestMediaContent::test_media_content_creation": 0.001162569999905827, - "src/backend/tests/unit/schema/test_content_types.py::TestMediaContent::test_media_content_without_caption": 0.0011367920001248422, - "src/backend/tests/unit/schema/test_content_types.py::TestTextContent::test_text_content_creation": 0.0011358500000824279, - "src/backend/tests/unit/schema/test_content_types.py::TestTextContent::test_text_content_with_duration": 0.0011214140004085493, - "src/backend/tests/unit/schema/test_content_types.py::TestToolContent::test_tool_content_creation": 0.001168671999948856, - "src/backend/tests/unit/schema/test_content_types.py::TestToolContent::test_tool_content_minimal": 0.001128386999880604, - "src/backend/tests/unit/schema/test_content_types.py::TestToolContent::test_tool_content_with_error": 0.0011355299998285773, - "src/backend/tests/unit/schema/test_content_types.py::test_content_type_discrimination": 0.0011927750001632376, - "src/backend/tests/unit/schema/test_image.py::test_get_file_paths": 0.006814541000494501, - "src/backend/tests/unit/schema/test_image.py::test_get_file_paths__empty": 0.0013146639998922183, - "src/backend/tests/unit/schema/test_image.py::test_get_files": 0.008064395000019431, - "src/backend/tests/unit/schema/test_image.py::test_get_files__convert_to_base64": 0.007873158999700536, - "src/backend/tests/unit/schema/test_image.py::test_get_files__empty": 0.0016543579999961366, - "src/backend/tests/unit/schema/test_image.py::test_is_image_file": 0.0020377750001898676, - "src/backend/tests/unit/schema/test_image.py::test_is_image_file__not_image": 0.0015996470001482521, - "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_ai_response": 0.001204269000027125, - "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_invalid_image_path": 0.0017618000001675682, - "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_missing_required_keys": 0.0012750099999720987, - "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_with_image": 0.00202325700001893, - "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_with_multiple_images": 0.0021008709995840036, - "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_with_text_only": 0.0012144679999437358, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_add_row_with_data_object": 0.003054664000046614, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_add_row_with_dict": 0.002992887999425875, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_add_rows_mixed_types": 0.002870958999665163, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_add_rows_with_data_objects": 0.002865208999992319, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_add_rows_with_dicts": 0.0028276300004108634, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_dataset_pandas_operations": 0.003845027999886952, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_dataset_type_preservation": 0.0024478400000589318, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_dataset_with_null_values": 0.0021183949997976015, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_from_data_list_basic": 0.0020761060000040743, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_from_data_list_empty": 0.001682439999513008, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_from_data_list_missing_fields": 0.0019585870004448225, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_from_data_list_nested_data": 0.0016835530000207655, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_data_objects": 0.0017716759998620546, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_dict_of_lists": 0.0017154219999611087, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_dicts": 0.0018119020000995079, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_invalid_list": 0.001516801999969175, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_kwargs": 0.0018255969998790533, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_none": 0.0013542579999921145, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_pandas_dataframe": 0.0017359809999106801, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_to_data_list_basic": 0.002376126999479311, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_to_data_list_empty": 0.0015473989997190074, - "src/backend/tests/unit/schema/test_schema_data_set.py::test_to_data_list_modified_data": 0.002782363000278565, - "src/backend/tests/unit/schema/test_schema_dataframe.py::TestDataFrameSchema::test_add_row": 0.00327337000044281, - "src/backend/tests/unit/schema/test_schema_dataframe.py::TestDataFrameSchema::test_add_rows": 0.0029757440001958457, - "src/backend/tests/unit/schema/test_schema_dataframe.py::TestDataFrameSchema::test_bool_operator": 0.0017048610002348141, - "src/backend/tests/unit/schema/test_schema_dataframe.py::TestDataFrameSchema::test_to_data_list": 0.0020417609994183294, - "src/backend/tests/unit/schema/test_schema_dataframe.py::TestDataFrameSchema::test_to_lc_documents": 0.0019805070000984415, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_is_list_attribute_processing": 0.0008677460000399151, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_is_list_handling": 0.0008854590000737517, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_missing_attributes_handling": 0.000798848000158614, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_missing_optional_attributes": 0.0008072639999454623, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_mixed_required_optional_fields_processing": 0.0012411320000182968, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_multiple_input_types": 0.00090810100005001, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_non_standard_field_types_handling": 0.0008165809999809426, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_none_default_value_handling": 0.0007980459998861988, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_options_attribute_processing": 0.0008994459999485116, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_options_handling": 0.0008625860000393004, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_passing_input_type_directly": 0.00046056799999405484, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_schema_model_creation": 0.0008055910000166477, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_single_input_type_conversion": 0.0008330699998850832, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_single_input_type_replica": 0.0008081149999270565, + "src/backend/tests/unit/io/test_io_schema.py::TestCreateInputSchema::test_special_characters_in_names_handling": 0.0007942589999174743, + "src/backend/tests/unit/io/test_io_schema.py::test_create_input_schema": 0.001943059000041103, + "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_create_column_with_valid_formatter": 0.0004494270000350298, + "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_create_column_without_display_name": 0.0004646260000527036, + "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_create_with_type_instead_of_formatter": 0.00043446000006497343, + "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_default_sortable_filterable": 0.00043870699994386086, + "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_description_and_default": 0.0004516110000167828, + "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_formatter_explicitly_set_to_enum": 0.00043867799990948697, + "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_formatter_none_when_not_provided": 0.0004624120000471521, + "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_formatter_set_based_on_value": 0.0004536659998848336, + "src/backend/tests/unit/io/test_table_schema.py::TestColumn::test_invalid_formatter_raises_value_error": 0.0005616549999558629, + "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_allow_markdown_override": 0.00043202399990605045, + "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_initialize_with_empty_contents": 0.0004326759999457863, + "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_initialize_with_valid_title_and_contents": 0.0006206660000316333, + "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_invalid_contents_type": 0.0005189370000380222, + "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_media_url_handling": 0.0004379549999384835, + "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_serialize_contents": 0.0005069929999308442, + "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_single_content_conversion": 0.0004610800000364179, + "src/backend/tests/unit/schema/test_content_block.py::TestContentBlock::test_validate_different_content_types": 0.0005015139998931772, + "src/backend/tests/unit/schema/test_content_types.py::TestBaseContent::test_base_content_serialization": 0.00048684599994430755, + "src/backend/tests/unit/schema/test_content_types.py::TestBaseContent::test_base_content_with_duration": 0.00042160500004229107, + "src/backend/tests/unit/schema/test_content_types.py::TestBaseContent::test_base_content_with_header": 0.00044598999988920696, + "src/backend/tests/unit/schema/test_content_types.py::TestCodeContent::test_code_content_creation": 0.0004456399999526184, + "src/backend/tests/unit/schema/test_content_types.py::TestCodeContent::test_code_content_without_title": 0.0004395880000629404, + "src/backend/tests/unit/schema/test_content_types.py::TestErrorContent::test_error_content_creation": 0.0004261540000243258, + "src/backend/tests/unit/schema/test_content_types.py::TestErrorContent::test_error_content_optional_fields": 0.0004228080000530099, + "src/backend/tests/unit/schema/test_content_types.py::TestJSONContent::test_json_content_complex_data": 0.0004502189999584516, + "src/backend/tests/unit/schema/test_content_types.py::TestJSONContent::test_json_content_creation": 0.0004199019999759912, + "src/backend/tests/unit/schema/test_content_types.py::TestMediaContent::test_media_content_creation": 0.0004447079999181369, + "src/backend/tests/unit/schema/test_content_types.py::TestMediaContent::test_media_content_without_caption": 0.0004189800000631294, + "src/backend/tests/unit/schema/test_content_types.py::TestTextContent::test_text_content_creation": 0.0004448079998837784, + "src/backend/tests/unit/schema/test_content_types.py::TestTextContent::test_text_content_with_duration": 0.0004446890000053827, + "src/backend/tests/unit/schema/test_content_types.py::TestToolContent::test_tool_content_creation": 0.0004214649998175446, + "src/backend/tests/unit/schema/test_content_types.py::TestToolContent::test_tool_content_minimal": 0.0004211139998915314, + "src/backend/tests/unit/schema/test_content_types.py::TestToolContent::test_tool_content_with_error": 0.00044189400000504975, + "src/backend/tests/unit/schema/test_content_types.py::test_content_type_discrimination": 0.00043243400000392285, + "src/backend/tests/unit/schema/test_image.py::test_get_file_paths": 0.004353788999878816, + "src/backend/tests/unit/schema/test_image.py::test_get_file_paths__empty": 0.0005339450000292345, + "src/backend/tests/unit/schema/test_image.py::test_get_files": 0.006616151999992326, + "src/backend/tests/unit/schema/test_image.py::test_get_files__convert_to_base64": 0.006464670000127626, + "src/backend/tests/unit/schema/test_image.py::test_get_files__empty": 0.0008111910000252465, + "src/backend/tests/unit/schema/test_image.py::test_is_image_file": 0.0012336979999645337, + "src/backend/tests/unit/schema/test_image.py::test_is_image_file__not_image": 0.0007717380001395213, + "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_ai_response": 0.0004977869999720497, + "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_invalid_image_path": 0.000846755999987181, + "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_missing_required_keys": 0.0005377410000164673, + "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_with_image": 0.0010502449999876262, + "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_with_multiple_images": 0.001101541999901201, + "src/backend/tests/unit/schema/test_schema_data.py::TestDataSchema::test_data_to_message_with_text_only": 0.00050662299997839, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_add_row_with_data_object": 0.0018233059998919998, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_add_row_with_dict": 0.0018630499998835148, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_add_rows_mixed_types": 0.0017488869999624512, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_add_rows_with_data_objects": 0.0017675429999144399, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_add_rows_with_dicts": 0.0017574629999899116, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_dataset_pandas_operations": 0.0025748170000952086, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_dataset_type_preservation": 0.001357018000021526, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_dataset_with_null_values": 0.0011962880000737641, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_from_data_list_basic": 0.0012104359999511871, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_from_data_list_empty": 0.0008153999998512518, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_from_data_list_missing_fields": 0.0010372120001420626, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_from_data_list_nested_data": 0.0008734570000115127, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_data_objects": 0.000930171999925733, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_dict_of_lists": 0.0008815709999225874, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_dicts": 0.0009158049999768991, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_invalid_list": 0.0007283770000867662, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_kwargs": 0.000992940999935854, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_none": 0.0005954079998673478, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_init_with_pandas_dataframe": 0.0008785859999989043, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_to_data_list_basic": 0.0012922159999106952, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_to_data_list_empty": 0.0007326330000978487, + "src/backend/tests/unit/schema/test_schema_data_set.py::test_to_data_list_modified_data": 0.0017241119999198418, + "src/backend/tests/unit/schema/test_schema_dataframe.py::TestDataFrameSchema::test_add_row": 0.002079252999919845, + "src/backend/tests/unit/schema/test_schema_dataframe.py::TestDataFrameSchema::test_add_rows": 0.0017790240000294943, + "src/backend/tests/unit/schema/test_schema_dataframe.py::TestDataFrameSchema::test_bool_operator": 0.0008708410000508593, + "src/backend/tests/unit/schema/test_schema_dataframe.py::TestDataFrameSchema::test_to_data_list": 0.001102522999985922, + "src/backend/tests/unit/schema/test_schema_dataframe.py::TestDataFrameSchema::test_to_lc_documents": 0.0010846300000366682, "src/backend/tests/unit/schema/test_schema_message.py::test_message_async_prompt_serialization": 0.00209424999775365, - "src/backend/tests/unit/schema/test_schema_message.py::test_message_from_ai_text": 0.0013541089997488598, - "src/backend/tests/unit/schema/test_schema_message.py::test_message_from_human_text": 0.0013266770001791883, - "src/backend/tests/unit/schema/test_schema_message.py::test_message_prompt_serialization": 0.005538629000511719, - "src/backend/tests/unit/schema/test_schema_message.py::test_message_serialization": 0.0014419520002775243, - "src/backend/tests/unit/schema/test_schema_message.py::test_message_to_lc_without_sender": 0.0013984410002194636, - "src/backend/tests/unit/schema/test_schema_message.py::test_message_with_invalid_image_path": 0.0015669759995944332, - "src/backend/tests/unit/schema/test_schema_message.py::test_message_with_multiple_images": 0.003450380999765912, - "src/backend/tests/unit/schema/test_schema_message.py::test_message_with_single_image": 0.0030518269995809533, - "src/backend/tests/unit/schema/test_schema_message.py::test_message_without_sender": 0.0013364650003495626, - "src/backend/tests/unit/schema/test_schema_message.py::test_timestamp_serialization": 0.002167716000258224, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_async_iterator_handling": 0.0013225289999354573, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_builtin_type_serialization": 0.001159736000772682, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_bytes_serialization": 0.06663447699975222, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_class_serialization": 0.014239204000205063, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_custom_type_serialization": 0.001161567999588442, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_datetime_serialization": 0.08070124699997905, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_decimal_serialization": 0.08430144699968878, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_dict_serialization": 0.3822375760005343, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_document_serialization": 0.0013530450000871497, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_enum_serialization": 0.0013377770001170575, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_fallback_serialization": 0.003902706000189937, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_generic_type_serialization": 0.0012817639994864294, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_instance_serialization": 0.0012833150003643823, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_list_truncation": 0.18263093199993818, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_max_items_none": 0.22610626899995623, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_max_length_none": 0.06943804100001216, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_nested_class_serialization": 0.011480372999812971, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_nested_structures": 0.47040150399971026, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_none_serialization": 0.0011467100002846564, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_numpy_int64_serialization": 0.0012014339999950607, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_numpy_numeric_serialization": 0.0013409129996944102, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_pandas_serialization": 0.0029487839997273113, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_primitive_types": 0.08044246500003283, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_pydantic_class_serialization": 0.0011867250000250351, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_pydantic_modern_model": 0.06481689400015966, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_pydantic_v1_model": 0.06763596700011476, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_series_serialization": 0.0013143940000190923, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_series_truncation": 0.0017299190003541298, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_string_serialization": 0.1331461230001878, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_type_alias_serialization": 0.001205750000281114, - "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_uuid_serialization": 0.07404041200061329, + "src/backend/tests/unit/schema/test_schema_message.py::test_message_from_ai_text": 0.000564160999942942, + "src/backend/tests/unit/schema/test_schema_message.py::test_message_from_human_text": 0.0005765839999867239, + "src/backend/tests/unit/schema/test_schema_message.py::test_message_prompt_serialization": 0.004082765000021027, + "src/backend/tests/unit/schema/test_schema_message.py::test_message_serialization": 0.0006620419999308069, + "src/backend/tests/unit/schema/test_schema_message.py::test_message_to_lc_without_sender": 0.0005675169999221907, + "src/backend/tests/unit/schema/test_schema_message.py::test_message_with_invalid_image_path": 0.0007580019998840726, + "src/backend/tests/unit/schema/test_schema_message.py::test_message_with_multiple_images": 0.002024892000008549, + "src/backend/tests/unit/schema/test_schema_message.py::test_message_with_single_image": 0.0018490049999400071, + "src/backend/tests/unit/schema/test_schema_message.py::test_message_without_sender": 0.0005725160000338292, + "src/backend/tests/unit/schema/test_schema_message.py::test_timestamp_serialization": 0.0011540589998730866, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_async_iterator_handling": 0.0005358090000981974, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_builtin_type_serialization": 0.0005141980000189506, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_bytes_serialization": 0.05161873599979572, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_class_serialization": 0.010843855999951302, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_custom_type_serialization": 0.0005095690002008268, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_datetime_serialization": 0.05792274800000996, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_decimal_serialization": 0.06365762899997662, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_dict_serialization": 0.2765686340000002, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_document_serialization": 0.000616207999883045, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_enum_serialization": 0.0006461829999580004, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_fallback_serialization": 0.002737789999969209, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_generic_type_serialization": 0.000553269999954864, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_instance_serialization": 0.000564451999935045, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_list_truncation": 0.13222654499998043, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_max_items_none": 0.1684969060000867, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_max_length_none": 0.051293672000042534, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_nested_class_serialization": 0.008548459999929037, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_nested_structures": 0.26250091400004294, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_none_serialization": 0.0005000409998956457, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_numpy_int64_serialization": 0.0005010429998719701, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_numpy_numeric_serialization": 0.0006292320000511609, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_pandas_serialization": 0.0018334750000121858, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_primitive_types": 0.06034337699998105, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_pydantic_class_serialization": 0.0005302280001160398, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_pydantic_modern_model": 0.049069518999885986, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_pydantic_v1_model": 0.049625353000010364, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_series_serialization": 0.0005751510000209237, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_series_truncation": 0.000910395999994762, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_string_serialization": 0.1045862449999504, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_type_alias_serialization": 0.0005010919999222097, + "src/backend/tests/unit/serialization/test_serialization.py::TestSerializationHypothesis::test_uuid_serialization": 0.053700686000070164, "src/backend/tests/unit/services/database/test_utils.py::test_truncate_json__large_case": 0.0013368430001037268, "src/backend/tests/unit/services/database/test_utils.py::test_truncate_json__small_case": 0.001604773000053683, - "src/backend/tests/unit/services/database/test_vertex_builds.py::test_concurrent_log_vertex_build": 0.2310918970001694, - "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_basic": 0.13560210500008907, - "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_integrity_error": 0.11880140299990671, - "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_max_global_limit": 9.227939421000428, - "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_max_per_vertex_limit": 0.12202339999976175, - "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_ordering": 0.12855027300020083, - "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_with_different_limits[1-1]": 0.12176934500030256, - "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_with_different_limits[100-50]": 0.6418940700000348, - "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_with_different_limits[5-3]": 0.15060662600035357, - "src/backend/tests/unit/services/flow/test_flow_runner.py::test_database_exists_check": 0.09902693999993062, - "src/backend/tests/unit/services/flow/test_flow_runner.py::test_get_flow_dict_from_dict": 0.0018447639999976673, - "src/backend/tests/unit/services/flow/test_flow_runner.py::test_get_flow_dict_invalid_input": 0.0017740520002007543, - "src/backend/tests/unit/services/flow/test_flow_runner.py::test_initialize_database": 6.4824630850002904, - "src/backend/tests/unit/services/flow/test_flow_runner.py::test_run_with_dict_input": 12.031674155000019, - "src/backend/tests/unit/services/flow/test_flow_runner.py::test_run_with_different_input_types": 7.893346652999753, - "src/backend/tests/unit/services/tasks/test_temp_flow_cleanup.py::test_cleanup_orphaned_records_no_orphans": 7.381443890000355, - "src/backend/tests/unit/services/tasks/test_temp_flow_cleanup.py::test_cleanup_orphaned_records_with_orphans": 7.421245819999967, - "src/backend/tests/unit/services/tasks/test_temp_flow_cleanup.py::test_cleanup_worker_run_with_exception": 0.0026011649993051833, - "src/backend/tests/unit/services/tasks/test_temp_flow_cleanup.py::test_cleanup_worker_start_stop": 0.00833886899999925, - "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_cleanup_inputs": 0.001537791000373545, - "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_concurrent_tracing": 4.009046855999713, - "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_deactivated_tracing": 0.0036029959996994876, - "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_get_langchain_callbacks": 0.0056091219998961606, - "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_start_end_tracers": 0.004602002000410721, - "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_start_tracers_with_exception": 0.003997934000381065, - "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_trace_component": 0.205732041000374, - "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_trace_component_with_exception": 0.10529649000045538, - "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_trace_worker_with_exception": 0.10532875400031116, - "src/backend/tests/unit/services/variable/test_service.py::test_create_variable": 0.09528680299945336, + "src/backend/tests/unit/services/database/test_vertex_builds.py::test_concurrent_log_vertex_build": 0.16283126600001196, + "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_basic": 0.08535057099993537, + "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_integrity_error": 0.08911698400004298, + "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_max_global_limit": 7.737121401999843, + "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_max_per_vertex_limit": 0.10640035399990211, + "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_ordering": 0.0944366749999972, + "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_with_different_limits[1-1]": 0.1013742849999062, + "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_with_different_limits[100-50]": 0.47385496300012164, + "src/backend/tests/unit/services/database/test_vertex_builds.py::test_log_vertex_build_with_different_limits[5-3]": 0.10165424700005588, + "src/backend/tests/unit/services/flow/test_flow_runner.py::test_database_exists_check": 0.061427429000104894, + "src/backend/tests/unit/services/flow/test_flow_runner.py::test_get_flow_dict_from_dict": 0.0008280020000484001, + "src/backend/tests/unit/services/flow/test_flow_runner.py::test_get_flow_dict_invalid_input": 0.0008668049999869254, + "src/backend/tests/unit/services/flow/test_flow_runner.py::test_initialize_database": 0.348645058999864, + "src/backend/tests/unit/services/flow/test_flow_runner.py::test_run_with_dict_input": 0.8427561930000138, + "src/backend/tests/unit/services/flow/test_flow_runner.py::test_run_with_different_input_types": 0.41872550700009015, + "src/backend/tests/unit/services/tasks/test_temp_flow_cleanup.py::test_cleanup_orphaned_records_no_orphans": 1.3858864040000753, + "src/backend/tests/unit/services/tasks/test_temp_flow_cleanup.py::test_cleanup_orphaned_records_with_orphans": 1.3552891559999125, + "src/backend/tests/unit/services/tasks/test_temp_flow_cleanup.py::test_cleanup_worker_run_with_exception": 0.0015979450000713769, + "src/backend/tests/unit/services/tasks/test_temp_flow_cleanup.py::test_cleanup_worker_start_stop": 0.004214729000068473, + "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_cleanup_inputs": 0.00077394200013714, + "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_concurrent_tracing": 4.007851697999968, + "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_deactivated_tracing": 0.0021704020000470337, + "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_get_langchain_callbacks": 0.0036817570000948763, + "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_start_end_tracers": 0.0029197269999485798, + "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_start_tracers_with_exception": 0.002448729999969146, + "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_trace_component": 0.20401882599992405, + "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_trace_component_with_exception": 0.10356234900007166, + "src/backend/tests/unit/services/tracing/test_tracing_service.py::test_trace_worker_with_exception": 0.10316488299986304, + "src/backend/tests/unit/services/variable/test_service.py::test_create_variable": 0.09158274499998242, "src/backend/tests/unit/services/variable/test_service.py::test_delete_varaible_by_id": 0.0060262500192038715, - "src/backend/tests/unit/services/variable/test_service.py::test_delete_variable": 0.09936810199997126, + "src/backend/tests/unit/services/variable/test_service.py::test_delete_variable": 0.0764697449999403, "src/backend/tests/unit/services/variable/test_service.py::test_delete_variable__ValueError": 0.0035743750049732625, - "src/backend/tests/unit/services/variable/test_service.py::test_delete_variable__valueerror": 0.09701722500039978, - "src/backend/tests/unit/services/variable/test_service.py::test_delete_variable_by_id": 0.09786453700053244, + "src/backend/tests/unit/services/variable/test_service.py::test_delete_variable__valueerror": 0.08547093399999994, + "src/backend/tests/unit/services/variable/test_service.py::test_delete_variable_by_id": 0.09440622700003587, "src/backend/tests/unit/services/variable/test_service.py::test_delete_variable_by_id__ValueError": 0.27340612601256, - "src/backend/tests/unit/services/variable/test_service.py::test_delete_variable_by_id__valueerror": 0.11319312899968281, - "src/backend/tests/unit/services/variable/test_service.py::test_get_variable": 0.09701271399990219, + "src/backend/tests/unit/services/variable/test_service.py::test_delete_variable_by_id__valueerror": 0.07412178399999902, + "src/backend/tests/unit/services/variable/test_service.py::test_get_variable": 0.07601206399999683, "src/backend/tests/unit/services/variable/test_service.py::test_get_variable__TypeError": 0.00458791694836691, "src/backend/tests/unit/services/variable/test_service.py::test_get_variable__ValueError": 0.003811584028881043, - "src/backend/tests/unit/services/variable/test_service.py::test_get_variable__typeerror": 0.11253405100023883, - "src/backend/tests/unit/services/variable/test_service.py::test_get_variable__valueerror": 0.09548929399988992, - "src/backend/tests/unit/services/variable/test_service.py::test_initialize_user_variables__create_and_update": 0.20227491400009967, + "src/backend/tests/unit/services/variable/test_service.py::test_get_variable__typeerror": 0.07518323100009638, + "src/backend/tests/unit/services/variable/test_service.py::test_get_variable__valueerror": 0.08203552700001637, + "src/backend/tests/unit/services/variable/test_service.py::test_initialize_user_variables__create_and_update": 0.14385618799997246, "src/backend/tests/unit/services/variable/test_service.py::test_initialize_user_variables__donkey": 0.0002315010060556233, - "src/backend/tests/unit/services/variable/test_service.py::test_initialize_user_variables__not_found_variable": 0.09759354000016174, - "src/backend/tests/unit/services/variable/test_service.py::test_initialize_user_variables__skipping_environment_variable_storage": 0.09413913200023671, - "src/backend/tests/unit/services/variable/test_service.py::test_list_variables": 0.10154578799983938, - "src/backend/tests/unit/services/variable/test_service.py::test_list_variables__empty": 0.10108964699975331, - "src/backend/tests/unit/services/variable/test_service.py::test_update_variable": 0.10170560700044007, + "src/backend/tests/unit/services/variable/test_service.py::test_initialize_user_variables__not_found_variable": 0.08468010499984757, + "src/backend/tests/unit/services/variable/test_service.py::test_initialize_user_variables__skipping_environment_variable_storage": 0.07833200599986867, + "src/backend/tests/unit/services/variable/test_service.py::test_list_variables": 0.07700179599999046, + "src/backend/tests/unit/services/variable/test_service.py::test_list_variables__empty": 0.07179814700009501, + "src/backend/tests/unit/services/variable/test_service.py::test_update_variable": 0.08082259599996178, "src/backend/tests/unit/services/variable/test_service.py::test_update_variable__ValueError": 0.0036237920285202563, - "src/backend/tests/unit/services/variable/test_service.py::test_update_variable__valueerror": 0.09474971100007679, - "src/backend/tests/unit/services/variable/test_service.py::test_update_variable_fields": 0.10074299000007159, - "src/backend/tests/unit/test_api_key.py::test_create_api_key": 7.487287394999839, - "src/backend/tests/unit/test_api_key.py::test_delete_api_key": 7.630280727999889, - "src/backend/tests/unit/test_api_key.py::test_get_api_keys": 7.4439161559998865, + "src/backend/tests/unit/services/variable/test_service.py::test_update_variable__valueerror": 0.07621568100000786, + "src/backend/tests/unit/services/variable/test_service.py::test_update_variable_fields": 0.07639314800007924, + "src/backend/tests/unit/test_api_key.py::test_create_api_key": 1.3673904310001035, + "src/backend/tests/unit/test_api_key.py::test_delete_api_key": 1.3898654339999439, + "src/backend/tests/unit/test_api_key.py::test_get_api_keys": 1.3538136249999297, "src/backend/tests/unit/test_cache.py::test_build_graph": 1.1988659180001378, - "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow": 5.557203025000035, - "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_from_request_data": 1.5691978709996874, - "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_invalid_flow_id": 1.5512351699999272, - "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_invalid_job_id": 1.5734577620000891, - "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_polling": 1.548397718999695, - "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_start_only": 1.5622727119998672, - "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_start_with_inputs": 1.542403679000472, - "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_with_frozen_path": 7.833314654999413, - "src/backend/tests/unit/test_chat_endpoint.py::test_cancel_build_failure": 1.616633347000061, - "src/backend/tests/unit/test_chat_endpoint.py::test_cancel_build_success": 1.5915307679997568, - "src/backend/tests/unit/test_chat_endpoint.py::test_cancel_build_unexpected_error": 1.5467227340000136, - "src/backend/tests/unit/test_chat_endpoint.py::test_cancel_build_with_cancelled_error": 1.5778230820001227, - "src/backend/tests/unit/test_chat_endpoint.py::test_cancel_nonexistent_build": 1.592972680999992, - "src/backend/tests/unit/test_cli.py::test_components_path": 0.3088522529992588, - "src/backend/tests/unit/test_cli.py::test_superuser": 7.324970772999677, - "src/backend/tests/unit/test_custom_component.py::test_build_config_field_keys": 0.001197205999687867, - "src/backend/tests/unit/test_custom_component.py::test_build_config_field_value_keys": 0.001180525000563648, - "src/backend/tests/unit/test_custom_component.py::test_build_config_field_values_dict": 0.001183100000162085, - "src/backend/tests/unit/test_custom_component.py::test_build_config_fields_dict": 0.0011766160005208803, - "src/backend/tests/unit/test_custom_component.py::test_build_config_has_fields": 0.0011823190002360207, - "src/backend/tests/unit/test_custom_component.py::test_build_config_no_code": 0.0011501689996293862, - "src/backend/tests/unit/test_custom_component.py::test_build_config_return_type": 0.0012124660001973098, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_get_tree": 0.0013280989996928838, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_init": 0.0012770050002473, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_ann_assign": 0.0011770790001719433, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_arg_no_annotation": 0.0011556189997463662, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_arg_with_annotation": 0.0011394279999876744, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_assign": 0.0011981369998466107, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_callable_details_no_args": 0.0011758659998122312, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_classes": 0.0017540250000820379, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_classes_raises": 0.0011957830006394943, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_function_def_init": 0.001170105000710464, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_function_def_not_init": 0.001177258000097936, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_functions": 0.0012157199998910073, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_global_vars": 0.0012222620002830809, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_imports_import": 0.001369888999761315, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_imports_importfrom": 0.001201784999921074, - "src/backend/tests/unit/test_custom_component.py::test_code_parser_syntax_error": 0.03119927000034295, - "src/backend/tests/unit/test_custom_component.py::test_component_code_null_error": 0.0012956800005667901, - "src/backend/tests/unit/test_custom_component.py::test_component_get_code_tree": 0.055228372999863495, - "src/backend/tests/unit/test_custom_component.py::test_component_get_code_tree_syntax_error": 0.001617039999928238, - "src/backend/tests/unit/test_custom_component.py::test_component_get_function_valid": 0.001235676999840507, - "src/backend/tests/unit/test_custom_component.py::test_component_init": 0.0011822379992736387, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_build_not_implemented": 0.001162179999937507, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_build_template_config": 0.002131691000158753, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_class_template_validation_no_code": 0.0011856249993797974, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_code_tree_syntax_error": 0.001560933999826375, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function": 0.001277765999930125, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function_entrypoint_args": 0.0026193329995294334, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function_entrypoint_args_no_args": 0.0018835979999494157, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function_entrypoint_return_type": 0.0025845270001809695, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function_entrypoint_return_type_no_return_type": 0.0018534709997766186, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function_valid": 0.0011706149998644833, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_main_class_name": 0.0026289689999430266, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_main_class_name_no_main_class": 0.0012715550005850673, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_init": 0.0011668799993458379, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_multiple_outputs": 0.008828878999793233, - "src/backend/tests/unit/test_custom_component.py::test_custom_component_subclass_from_lctoolcomponent": 0.005663165999976627, + "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow": 1.3780063809999774, + "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_from_request_data": 5.316480957999943, + "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_invalid_flow_id": 1.4013408140000365, + "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_invalid_job_id": 1.342623741999887, + "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_polling": 1.369279274000064, + "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_start_only": 1.368693181000026, + "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_start_with_inputs": 1.3557782450001241, + "src/backend/tests/unit/test_chat_endpoint.py::test_build_flow_with_frozen_path": 1.34781847499994, + "src/backend/tests/unit/test_chat_endpoint.py::test_cancel_build_failure": 1.4022172930000352, + "src/backend/tests/unit/test_chat_endpoint.py::test_cancel_build_success": 1.3803808760000038, + "src/backend/tests/unit/test_chat_endpoint.py::test_cancel_build_unexpected_error": 1.3835338430000093, + "src/backend/tests/unit/test_chat_endpoint.py::test_cancel_build_with_cancelled_error": 1.376216182000121, + "src/backend/tests/unit/test_chat_endpoint.py::test_cancel_nonexistent_build": 1.3723959699999568, + "src/backend/tests/unit/test_cli.py::test_components_path": 0.23740689000010207, + "src/backend/tests/unit/test_cli.py::test_superuser": 1.3209994129999814, + "src/backend/tests/unit/test_custom_component.py::test_build_config_field_keys": 0.00048317000005226873, + "src/backend/tests/unit/test_custom_component.py::test_build_config_field_value_keys": 0.0004828289999068147, + "src/backend/tests/unit/test_custom_component.py::test_build_config_field_values_dict": 0.0004832199998645592, + "src/backend/tests/unit/test_custom_component.py::test_build_config_fields_dict": 0.0004877989999840793, + "src/backend/tests/unit/test_custom_component.py::test_build_config_has_fields": 0.0004842109998435262, + "src/backend/tests/unit/test_custom_component.py::test_build_config_no_code": 0.00047265100010918104, + "src/backend/tests/unit/test_custom_component.py::test_build_config_return_type": 0.0005024349998166144, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_get_tree": 0.0006213270000898774, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_init": 0.000523033999911604, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_ann_assign": 0.000493329000050835, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_arg_no_annotation": 0.00044907599999532977, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_arg_with_annotation": 0.0004499279999663486, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_assign": 0.00047833099995386874, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_callable_details_no_args": 0.0004740240000273843, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_classes": 0.0009235000001126537, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_classes_raises": 0.0004945009999346439, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_function_def_init": 0.0004667610000979039, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_function_def_not_init": 0.0005002720000675254, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_functions": 0.00053131000004214, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_global_vars": 0.0004962849999401442, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_imports_import": 0.0006243530000347164, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_parse_imports_importfrom": 0.0005149389999132836, + "src/backend/tests/unit/test_custom_component.py::test_code_parser_syntax_error": 0.001152676999936375, + "src/backend/tests/unit/test_custom_component.py::test_component_code_null_error": 0.000653146999979981, + "src/backend/tests/unit/test_custom_component.py::test_component_get_code_tree": 0.04441865499995856, + "src/backend/tests/unit/test_custom_component.py::test_component_get_code_tree_syntax_error": 0.0008199769998782358, + "src/backend/tests/unit/test_custom_component.py::test_component_get_function_valid": 0.0006030140000348183, + "src/backend/tests/unit/test_custom_component.py::test_component_init": 0.000493459000040275, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_build_not_implemented": 0.00045537799985595484, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_build_template_config": 0.0011429979998638373, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_class_template_validation_no_code": 0.0004667789999075467, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_code_tree_syntax_error": 0.0007713869999861345, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function": 0.0005943259999412476, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function_entrypoint_args": 0.0018464170001379898, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function_entrypoint_args_no_args": 0.0009761579999576497, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function_entrypoint_return_type": 0.0015279169998621, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function_entrypoint_return_type_no_return_type": 0.000997587999904681, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_function_valid": 0.0004675200000292534, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_main_class_name": 0.0015303189999258393, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_get_main_class_name_no_main_class": 0.0005520869999600109, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_init": 0.0005009840001548582, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_multiple_outputs": 0.0042285440001705865, + "src/backend/tests/unit/test_custom_component.py::test_custom_component_subclass_from_lctoolcomponent": 0.002788070999940828, "src/backend/tests/unit/test_custom_component.py::test_list_flows_flow_objects": 1.981454541994026, "src/backend/tests/unit/test_custom_component.py::test_list_flows_return_type": 0.36947908403817564, "src/backend/tests/unit/test_custom_component_with_client.py::test_feature_flags_add_toolkit_output": 2.7484489580092486, - "src/backend/tests/unit/test_custom_component_with_client.py::test_list_flows_flow_objects": 7.397546083000179, - "src/backend/tests/unit/test_custom_component_with_client.py::test_list_flows_return_type": 7.4385269209997205, - "src/backend/tests/unit/test_data_class.py::test_add_method_for_integers": 0.0012034779997520673, - "src/backend/tests/unit/test_data_class.py::test_add_method_for_strings": 0.001201345000481524, - "src/backend/tests/unit/test_data_class.py::test_add_method_with_non_overlapping_keys": 0.0011861459997817292, - "src/backend/tests/unit/test_data_class.py::test_conversion_from_document": 0.001199571000142896, - "src/backend/tests/unit/test_data_class.py::test_conversion_to_document": 0.0012071040005139366, - "src/backend/tests/unit/test_data_class.py::test_custom_attribute_get_set_del": 0.0012177949997749238, - "src/backend/tests/unit/test_data_class.py::test_custom_attribute_setting_and_getting": 0.0011854639997181948, - "src/backend/tests/unit/test_data_class.py::test_data_initialization": 0.0013735850002376537, - "src/backend/tests/unit/test_data_class.py::test_deep_copy": 0.00120355799981553, - "src/backend/tests/unit/test_data_class.py::test_dir_includes_data_keys": 0.0012793599998985883, - "src/backend/tests/unit/test_data_class.py::test_dir_reflects_attribute_deletion": 0.0012857020001320052, - "src/backend/tests/unit/test_data_class.py::test_get_text_with_empty_data": 0.001152551999894058, - "src/backend/tests/unit/test_data_class.py::test_get_text_with_none_data": 0.0011853030000565923, - "src/backend/tests/unit/test_data_class.py::test_get_text_with_text_key": 0.001199701000132336, - "src/backend/tests/unit/test_data_class.py::test_get_text_without_text_key": 0.0011708959996212798, - "src/backend/tests/unit/test_data_class.py::test_str_and_dir_methods": 0.0013425670003925916, - "src/backend/tests/unit/test_data_class.py::test_validate_data_with_extra_keys": 0.0012361590002001321, + "src/backend/tests/unit/test_custom_component_with_client.py::test_list_flows_flow_objects": 1.3970667399999002, + "src/backend/tests/unit/test_custom_component_with_client.py::test_list_flows_return_type": 1.3811266129999922, + "src/backend/tests/unit/test_data_class.py::test_add_method_for_integers": 0.0004909640001642401, + "src/backend/tests/unit/test_data_class.py::test_add_method_for_strings": 0.00048714700005803024, + "src/backend/tests/unit/test_data_class.py::test_add_method_with_non_overlapping_keys": 0.0004958419999638863, + "src/backend/tests/unit/test_data_class.py::test_conversion_from_document": 0.00047414300001946685, + "src/backend/tests/unit/test_data_class.py::test_conversion_to_document": 0.0004791220000015528, + "src/backend/tests/unit/test_data_class.py::test_custom_attribute_get_set_del": 0.0004868570000553518, + "src/backend/tests/unit/test_data_class.py::test_custom_attribute_setting_and_getting": 0.0004832489998989331, + "src/backend/tests/unit/test_data_class.py::test_data_initialization": 0.0006179509998673893, + "src/backend/tests/unit/test_data_class.py::test_deep_copy": 0.000507534999883319, + "src/backend/tests/unit/test_data_class.py::test_dir_includes_data_keys": 0.0005894280001257357, + "src/backend/tests/unit/test_data_class.py::test_dir_reflects_attribute_deletion": 0.0005968410000605218, + "src/backend/tests/unit/test_data_class.py::test_get_text_with_empty_data": 0.00047716799997488124, + "src/backend/tests/unit/test_data_class.py::test_get_text_with_none_data": 0.0004683019999447424, + "src/backend/tests/unit/test_data_class.py::test_get_text_with_text_key": 0.0005054919998883634, + "src/backend/tests/unit/test_data_class.py::test_get_text_without_text_key": 0.0004956330000140952, + "src/backend/tests/unit/test_data_class.py::test_str_and_dir_methods": 0.0006173780000153783, + "src/backend/tests/unit/test_data_class.py::test_validate_data_with_extra_keys": 0.000497345999974641, "src/backend/tests/unit/test_data_components.py::test_build_with_multiple_urls": 2.1151568749919534, "src/backend/tests/unit/test_data_components.py::test_directory_component_build_with_multithreading": 0.011123959033284336, "src/backend/tests/unit/test_data_components.py::test_directory_without_mocks": 0.17772862600395456, @@ -1623,143 +1703,156 @@ "src/backend/tests/unit/test_data_components.py::test_successful_get_request": 0.04254975001094863, "src/backend/tests/unit/test_data_components.py::test_timeout": 0.023703540966380388, "src/backend/tests/unit/test_data_components.py::test_url_component": 2.0934785840217955, - "src/backend/tests/unit/test_database.py::test_create_flow": 11.467735999999604, - "src/backend/tests/unit/test_database.py::test_create_flow_with_invalid_data": 7.569698558000255, - "src/backend/tests/unit/test_database.py::test_create_flows": 7.793328612000096, - "src/backend/tests/unit/test_database.py::test_delete_flow": 7.623841104000348, - "src/backend/tests/unit/test_database.py::test_delete_flows": 7.579372856000646, - "src/backend/tests/unit/test_database.py::test_delete_flows_with_transaction_and_build": 7.531722480000099, - "src/backend/tests/unit/test_database.py::test_delete_folder_with_flows_with_transaction_and_build": 7.657938327000011, - "src/backend/tests/unit/test_database.py::test_delete_nonexistent_flow": 8.574833290999777, - "src/backend/tests/unit/test_database.py::test_download_file": 7.5889882489996126, - "src/backend/tests/unit/test_database.py::test_get_flows_from_folder_pagination": 12.534010063000096, - "src/backend/tests/unit/test_database.py::test_get_flows_from_folder_pagination_with_params": 7.984205585000382, - "src/backend/tests/unit/test_database.py::test_get_nonexistent_flow": 7.609064569000111, + "src/backend/tests/unit/test_database.py::test_create_flow": 1.4416482809999707, + "src/backend/tests/unit/test_database.py::test_create_flow_with_invalid_data": 1.4590850909999062, + "src/backend/tests/unit/test_database.py::test_create_flows": 1.4823309140000447, + "src/backend/tests/unit/test_database.py::test_delete_flow": 1.431831276000139, + "src/backend/tests/unit/test_database.py::test_delete_flows": 1.4626722880000216, + "src/backend/tests/unit/test_database.py::test_delete_flows_with_transaction_and_build": 1.4799293909999278, + "src/backend/tests/unit/test_database.py::test_delete_folder_with_flows_with_transaction_and_build": 1.431508550999979, + "src/backend/tests/unit/test_database.py::test_delete_nonexistent_flow": 1.4731047860000217, + "src/backend/tests/unit/test_database.py::test_download_file": 1.4278819290000229, + "src/backend/tests/unit/test_database.py::test_get_flows_from_folder_pagination": 1.4398938970000472, + "src/backend/tests/unit/test_database.py::test_get_flows_from_folder_pagination_with_params": 1.4443958660000362, + "src/backend/tests/unit/test_database.py::test_get_nonexistent_flow": 1.4411902470001223, "src/backend/tests/unit/test_database.py::test_load_flows": 2.0784470409998903, "src/backend/tests/unit/test_database.py::test_migrate_transactions": 3.3142859160434455, "src/backend/tests/unit/test_database.py::test_migrate_transactions_no_duckdb": 4.5406213329406455, - "src/backend/tests/unit/test_database.py::test_read_flow": 7.579777859000387, - "src/backend/tests/unit/test_database.py::test_read_flows": 7.471752969000136, - "src/backend/tests/unit/test_database.py::test_read_flows_components_only": 7.65115004900008, - "src/backend/tests/unit/test_database.py::test_read_flows_components_only_paginated": 7.879070536000199, - "src/backend/tests/unit/test_database.py::test_read_flows_custom_page_size": 7.5964207810002335, - "src/backend/tests/unit/test_database.py::test_read_flows_invalid_page": 7.569565668999985, - "src/backend/tests/unit/test_database.py::test_read_flows_invalid_size": 7.650162998999349, - "src/backend/tests/unit/test_database.py::test_read_flows_no_pagination_params": 7.540424083999824, - "src/backend/tests/unit/test_database.py::test_read_flows_pagination_with_flows": 7.46983351200015, - "src/backend/tests/unit/test_database.py::test_read_flows_pagination_with_params": 7.514467352999873, + "src/backend/tests/unit/test_database.py::test_read_flow": 1.4657151469998553, + "src/backend/tests/unit/test_database.py::test_read_flows": 5.742706833000057, + "src/backend/tests/unit/test_database.py::test_read_flows_components_only": 1.4231669219999503, + "src/backend/tests/unit/test_database.py::test_read_flows_components_only_paginated": 1.475713412999994, + "src/backend/tests/unit/test_database.py::test_read_flows_custom_page_size": 1.4156089789998987, + "src/backend/tests/unit/test_database.py::test_read_flows_invalid_page": 1.4194957189999968, + "src/backend/tests/unit/test_database.py::test_read_flows_invalid_size": 1.4469134779999422, + "src/backend/tests/unit/test_database.py::test_read_flows_no_pagination_params": 1.4050277669999787, + "src/backend/tests/unit/test_database.py::test_read_flows_pagination_with_flows": 1.3811027320000449, + "src/backend/tests/unit/test_database.py::test_read_flows_pagination_with_params": 1.412112167000032, "src/backend/tests/unit/test_database.py::test_read_flows_pagination_without_params": 2.8355551669956185, - "src/backend/tests/unit/test_database.py::test_read_folder": 8.024965343999611, - "src/backend/tests/unit/test_database.py::test_read_folder_with_component_filter": 8.012275503000183, - "src/backend/tests/unit/test_database.py::test_read_folder_with_flows": 7.799930265000057, - "src/backend/tests/unit/test_database.py::test_read_folder_with_pagination": 9.361740817999816, - "src/backend/tests/unit/test_database.py::test_read_folder_with_search": 7.943054303000281, - "src/backend/tests/unit/test_database.py::test_read_nonexistent_folder": 7.954883805000009, - "src/backend/tests/unit/test_database.py::test_read_only_starter_projects": 7.991675143000066, - "src/backend/tests/unit/test_database.py::test_sqlite_pragmas": 0.11112214299964762, - "src/backend/tests/unit/test_database.py::test_update_flow": 7.722285735999776, - "src/backend/tests/unit/test_database.py::test_update_flow_idempotency": 7.763861980999991, - "src/backend/tests/unit/test_database.py::test_update_nonexistent_flow": 7.789536455999951, - "src/backend/tests/unit/test_database.py::test_upload_file": 7.587887343999682, - "src/backend/tests/unit/test_endpoints.py::test_build_vertex_invalid_flow_id": 7.903600444999483, - "src/backend/tests/unit/test_endpoints.py::test_build_vertex_invalid_vertex_id": 7.734093682000093, - "src/backend/tests/unit/test_endpoints.py::test_concurrent_stream_run_with_input_type_chat": 7.614737654000237, - "src/backend/tests/unit/test_endpoints.py::test_get_all": 1.6706990000002406, - "src/backend/tests/unit/test_endpoints.py::test_get_vertices": 7.622446305000267, - "src/backend/tests/unit/test_endpoints.py::test_get_vertices_flow_not_found": 7.6658215610004845, - "src/backend/tests/unit/test_endpoints.py::test_invalid_flow_id": 7.68120169399981, - "src/backend/tests/unit/test_endpoints.py::test_invalid_prompt": 7.666892719000316, - "src/backend/tests/unit/test_endpoints.py::test_invalid_run_with_input_type_chat": 1.7653696090001176, - "src/backend/tests/unit/test_endpoints.py::test_post_validate_code": 7.835435351999877, - "src/backend/tests/unit/test_endpoints.py::test_starter_projects": 1.7481923920004192, - "src/backend/tests/unit/test_endpoints.py::test_successful_run_no_payload": 7.829969560000336, - "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_input_type_any": 1.732272587999887, - "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_input_type_chat": 1.6871633549999387, - "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_input_type_text": 1.7065058890002547, - "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_output_type_any": 1.7267665040003521, - "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_output_type_debug": 1.6918224149999332, - "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_output_type_text": 7.989863276000051, - "src/backend/tests/unit/test_endpoints.py::test_valid_prompt": 7.901349827000104, - "src/backend/tests/unit/test_endpoints.py::test_various_prompts[The weather is {weather} today.-expected_input_variables1]": 7.68536339100001, - "src/backend/tests/unit/test_endpoints.py::test_various_prompts[This prompt has no variables.-expected_input_variables2]": 7.644616878999841, - "src/backend/tests/unit/test_endpoints.py::test_various_prompts[{a}, {b}, and {c} are variables.-expected_input_variables3]": 7.713081766999949, - "src/backend/tests/unit/test_endpoints.py::test_various_prompts[{color} is my favorite color.-expected_input_variables0]": 7.653479334999702, - "src/backend/tests/unit/test_experimental_components.py::test_python_function_component": 0.003182294999533042, + "src/backend/tests/unit/test_database.py::test_read_folder": 1.4426041430000396, + "src/backend/tests/unit/test_database.py::test_read_folder_with_component_filter": 1.4680104419999225, + "src/backend/tests/unit/test_database.py::test_read_folder_with_flows": 1.4976142009999194, + "src/backend/tests/unit/test_database.py::test_read_folder_with_pagination": 1.454027850999978, + "src/backend/tests/unit/test_database.py::test_read_folder_with_search": 1.4485818679999056, + "src/backend/tests/unit/test_database.py::test_read_nonexistent_folder": 1.4417218550000825, + "src/backend/tests/unit/test_database.py::test_read_only_starter_projects": 1.4518444779999982, + "src/backend/tests/unit/test_database.py::test_sqlite_pragmas": 0.08172290799996063, + "src/backend/tests/unit/test_database.py::test_update_flow": 1.4008895850000727, + "src/backend/tests/unit/test_database.py::test_update_flow_idempotency": 1.4034884089999196, + "src/backend/tests/unit/test_database.py::test_update_nonexistent_flow": 1.51179056400008, + "src/backend/tests/unit/test_database.py::test_upload_file": 1.4413808670000208, + "src/backend/tests/unit/test_endpoints.py::test_build_vertex_invalid_flow_id": 1.4596974359999422, + "src/backend/tests/unit/test_endpoints.py::test_build_vertex_invalid_vertex_id": 1.495432735999998, + "src/backend/tests/unit/test_endpoints.py::test_concurrent_stream_run_with_input_type_chat": 1.5048681120000538, + "src/backend/tests/unit/test_endpoints.py::test_get_all": 1.5173383679999688, + "src/backend/tests/unit/test_endpoints.py::test_get_vertices": 1.502541320999967, + "src/backend/tests/unit/test_endpoints.py::test_get_vertices_flow_not_found": 1.54064245699999, + "src/backend/tests/unit/test_endpoints.py::test_invalid_flow_id": 1.553026454000019, + "src/backend/tests/unit/test_endpoints.py::test_invalid_prompt": 7.0824514650000765, + "src/backend/tests/unit/test_endpoints.py::test_invalid_run_with_input_type_chat": 1.5597121529998503, + "src/backend/tests/unit/test_endpoints.py::test_post_validate_code": 1.4553498960000297, + "src/backend/tests/unit/test_endpoints.py::test_starter_projects": 1.5608298830001104, + "src/backend/tests/unit/test_endpoints.py::test_successful_run_no_payload": 1.4828401150000445, + "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_input_type_any": 1.5500291989999369, + "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_input_type_chat": 1.5335983790000682, + "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_input_type_text": 1.5080489530000705, + "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_output_type_any": 1.4948378480000883, + "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_output_type_debug": 1.487990759000013, + "src/backend/tests/unit/test_endpoints.py::test_successful_run_with_output_type_text": 1.4642057229999637, + "src/backend/tests/unit/test_endpoints.py::test_valid_prompt": 1.4891053419999025, + "src/backend/tests/unit/test_endpoints.py::test_various_prompts[The weather is {weather} today.-expected_input_variables1]": 1.4853942119999601, + "src/backend/tests/unit/test_endpoints.py::test_various_prompts[This prompt has no variables.-expected_input_variables2]": 1.4954424049999488, + "src/backend/tests/unit/test_endpoints.py::test_various_prompts[{a}, {b}, and {c} are variables.-expected_input_variables3]": 1.4545287470000403, + "src/backend/tests/unit/test_endpoints.py::test_various_prompts[{color} is my favorite color.-expected_input_variables0]": 1.4943664389999185, + "src/backend/tests/unit/test_experimental_components.py::test_python_function_component": 0.0012624209999785307, "src/backend/tests/unit/test_files.py::test_delete_file": 11.937014124996495, "src/backend/tests/unit/test_files.py::test_download_file": 9.813468083040789, "src/backend/tests/unit/test_files.py::test_file_operations": 11.151997918030247, "src/backend/tests/unit/test_files.py::test_list_files": 11.372431917930953, "src/backend/tests/unit/test_files.py::test_upload_file": 9.378826959000435, - "src/backend/tests/unit/test_frontend_nodes.py::test_frontend_node_to_dict": 0.0014794539997637912, - "src/backend/tests/unit/test_frontend_nodes.py::test_template_field_defaults": 0.001301601999784907, - "src/backend/tests/unit/test_frontend_nodes.py::test_template_to_dict": 0.001389526000366459, - "src/backend/tests/unit/test_helper_components.py::test_data_as_text_component": 0.002238431000023411, - "src/backend/tests/unit/test_helper_components.py::test_uuid_generator_component": 0.008946774000378355, - "src/backend/tests/unit/test_initial_setup.py::test_create_or_update_starter_projects": 7.827434874000119, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://example.com/myzip.zip-https://example.com/myzip.zip]": 0.002203876999374188, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/main.zip]": 0.026558390999525727, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles.git-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/main.zip]": 0.025697873000353866, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/main.zip]": 0.025899320000462467, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/commit/68428ce16729a385fe1bcc0f1ec91fd5f5f420b9-https://github.com/langflow-ai/langflow-bundles/archive/68428ce16729a385fe1bcc0f1ec91fd5f5f420b9.zip]": 0.0024325129998032935, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/commit/68428ce16729a385fe1bcc0f1ec91fd5f5f420b9/-https://github.com/langflow-ai/langflow-bundles/archive/68428ce16729a385fe1bcc0f1ec91fd5f5f420b9.zip]": 0.002238852999653318, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/releases/tag/foo/v1.0.0-https://github.com/langflow-ai/langflow-bundles/archive/refs/tags/foo/v1.0.0.zip]": 0.0022568059998775425, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/releases/tag/foo/v1.0.0/-https://github.com/langflow-ai/langflow-bundles/archive/refs/tags/foo/v1.0.0.zip]": 0.0025909400005730276, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/releases/tag/v1.0.0-0_1-https://github.com/langflow-ai/langflow-bundles/archive/refs/tags/v1.0.0-0_1.zip]": 0.002417226000034134, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/tree/some.branch-0_1-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/some.branch-0_1.zip]": 0.002960699999675853, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/tree/some/branch-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/some/branch.zip]": 0.0024308009997184854, - "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/tree/some/branch/-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/some/branch.zip]": 0.002367013000366569, - "src/backend/tests/unit/test_initial_setup.py::test_get_project_data": 0.0032980320006572583, - "src/backend/tests/unit/test_initial_setup.py::test_load_bundles_from_urls": 7.6780357800003, - "src/backend/tests/unit/test_initial_setup.py::test_load_starter_projects": 0.003513863000080164, - "src/backend/tests/unit/test_initial_setup.py::test_refresh_starter_projects": 6.543067887000234, - "src/backend/tests/unit/test_initial_setup.py::test_sync_flows_from_fs": 7.67438837599957, - "src/backend/tests/unit/test_kubernetes_secrets.py::test_create_secret": 0.004190811999706057, - "src/backend/tests/unit/test_kubernetes_secrets.py::test_delete_secret": 0.003015677999883337, - "src/backend/tests/unit/test_kubernetes_secrets.py::test_email_address": 0.001217393000388256, - "src/backend/tests/unit/test_kubernetes_secrets.py::test_encode_string": 0.0012184739998701843, - "src/backend/tests/unit/test_kubernetes_secrets.py::test_encode_uuid": 0.0012474789996304025, - "src/backend/tests/unit/test_kubernetes_secrets.py::test_ends_with_non_alphanumeric": 0.0012130350000916224, - "src/backend/tests/unit/test_kubernetes_secrets.py::test_get_secret": 0.002657229999840638, - "src/backend/tests/unit/test_kubernetes_secrets.py::test_long_string": 0.0015233119993354194, - "src/backend/tests/unit/test_kubernetes_secrets.py::test_starts_with_non_alphanumeric": 0.0012040470001011272, - "src/backend/tests/unit/test_kubernetes_secrets.py::test_uuid_case_insensitivity": 0.001198456999645714, + "src/backend/tests/unit/test_frontend_nodes.py::test_frontend_node_to_dict": 0.0007452780000676285, + "src/backend/tests/unit/test_frontend_nodes.py::test_template_field_defaults": 0.0005897079998931076, + "src/backend/tests/unit/test_frontend_nodes.py::test_template_to_dict": 0.0006518849999110898, + "src/backend/tests/unit/test_helper_components.py::test_data_as_text_component": 0.0008412469998120287, + "src/backend/tests/unit/test_helper_components.py::test_uuid_generator_component": 0.002719153999919399, + "src/backend/tests/unit/test_initial_setup.py::test_create_or_update_starter_projects": 1.5052192659999264, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://example.com/myzip.zip-https://example.com/myzip.zip]": 0.0013754919999655613, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/main.zip]": 0.021449715000017022, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles.git-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/main.zip]": 0.020703224000158116, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/main.zip]": 0.020794162000015604, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/commit/68428ce16729a385fe1bcc0f1ec91fd5f5f420b9-https://github.com/langflow-ai/langflow-bundles/archive/68428ce16729a385fe1bcc0f1ec91fd5f5f420b9.zip]": 0.0015107229999102856, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/commit/68428ce16729a385fe1bcc0f1ec91fd5f5f420b9/-https://github.com/langflow-ai/langflow-bundles/archive/68428ce16729a385fe1bcc0f1ec91fd5f5f420b9.zip]": 0.0013505050000048868, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/releases/tag/foo/v1.0.0-https://github.com/langflow-ai/langflow-bundles/archive/refs/tags/foo/v1.0.0.zip]": 0.0013854099998980018, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/releases/tag/foo/v1.0.0/-https://github.com/langflow-ai/langflow-bundles/archive/refs/tags/foo/v1.0.0.zip]": 0.0013234630000624747, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/releases/tag/v1.0.0-0_1-https://github.com/langflow-ai/langflow-bundles/archive/refs/tags/v1.0.0-0_1.zip]": 0.001743978000149582, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/tree/some.branch-0_1-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/some.branch-0_1.zip]": 0.001597685000092497, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/tree/some/branch-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/some/branch.zip]": 0.0013864009999906557, + "src/backend/tests/unit/test_initial_setup.py::test_detect_github_url[https://github.com/langflow-ai/langflow-bundles/tree/some/branch/-https://github.com/langflow-ai/langflow-bundles/archive/refs/heads/some/branch.zip]": 0.0016282920000776357, + "src/backend/tests/unit/test_initial_setup.py::test_get_project_data": 0.001993332999973063, + "src/backend/tests/unit/test_initial_setup.py::test_load_bundles_from_urls": 1.5328599169999961, + "src/backend/tests/unit/test_initial_setup.py::test_load_starter_projects": 0.0021000809999804915, + "src/backend/tests/unit/test_initial_setup.py::test_refresh_starter_projects": 4.726206988999934, + "src/backend/tests/unit/test_initial_setup.py::test_sync_flows_from_fs": 1.559571826000024, + "src/backend/tests/unit/test_kubernetes_secrets.py::test_create_secret": 0.0027814000000034866, + "src/backend/tests/unit/test_kubernetes_secrets.py::test_delete_secret": 0.0017491179999069573, + "src/backend/tests/unit/test_kubernetes_secrets.py::test_email_address": 0.00045235200013848953, + "src/backend/tests/unit/test_kubernetes_secrets.py::test_encode_string": 0.00048353999989103613, + "src/backend/tests/unit/test_kubernetes_secrets.py::test_encode_uuid": 0.0005308480000394411, + "src/backend/tests/unit/test_kubernetes_secrets.py::test_ends_with_non_alphanumeric": 0.00047370199990837136, + "src/backend/tests/unit/test_kubernetes_secrets.py::test_get_secret": 0.001612773000033485, + "src/backend/tests/unit/test_kubernetes_secrets.py::test_long_string": 0.0004911040000479261, + "src/backend/tests/unit/test_kubernetes_secrets.py::test_starts_with_non_alphanumeric": 0.0004677120000451396, + "src/backend/tests/unit/test_kubernetes_secrets.py::test_uuid_case_insensitivity": 0.00047664699991400994, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_aget_all_types_dict_basic": 4.6982535010000674, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_component_differences_analysis": 6.209356759999764, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_component_loading_performance": 1.4057227500002227, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_component_loading_performance_comparison": 12.301237360000073, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_component_template_structure": 1.4306151860000682, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_components_path_variations": 9.584205702999952, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_comprehensive_performance_summary": 31.24968936900018, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_concurrent_loading": 7.788794050999968, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_error_handling": 1.419609497000124, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_get_langflow_components_list_basic": 1.426067396999997, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_memory_efficiency": 21.566328941000165, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_repeated_loading_performance": 37.41391714899987, + "src/backend/tests/unit/test_load_components.py::TestComponentLoading::test_result_structure_comparison": 12.371470391000003, "src/backend/tests/unit/test_loading.py::test_load_flow_from_json": 1.2976477909833193, - "src/backend/tests/unit/test_loading.py::test_load_flow_from_json_object": 0.0031783819995325757, + "src/backend/tests/unit/test_loading.py::test_load_flow_from_json_object": 0.0019824969997443986, "src/backend/tests/unit/test_loading.py::test_load_flow_from_json_with_tweaks": 0.005636290996335447, - "src/backend/tests/unit/test_logger.py::test_enabled": 0.0011617679997470987, - "src/backend/tests/unit/test_logger.py::test_get_after_timestamp": 0.0012417679999998654, - "src/backend/tests/unit/test_logger.py::test_get_before_timestamp": 0.0012647100002141087, - "src/backend/tests/unit/test_logger.py::test_get_last_n": 0.0012337229995864618, - "src/backend/tests/unit/test_logger.py::test_init_default": 0.0011743019999812532, - "src/backend/tests/unit/test_logger.py::test_init_with_env_variable": 0.0017638230001466582, - "src/backend/tests/unit/test_logger.py::test_len": 0.001215678999415104, - "src/backend/tests/unit/test_logger.py::test_max_size": 0.0011792010000135633, - "src/backend/tests/unit/test_logger.py::test_write": 0.0012689069999396452, - "src/backend/tests/unit/test_logger.py::test_write_overflow": 0.0012345849995654135, - "src/backend/tests/unit/test_login.py::test_login_successful": 7.6207168370001455, - "src/backend/tests/unit/test_login.py::test_login_unsuccessful_wrong_password": 7.71390041199993, - "src/backend/tests/unit/test_login.py::test_login_unsuccessful_wrong_username": 7.6177526540000144, - "src/backend/tests/unit/test_messages.py::test_aadd_messages": 7.707115792999957, - "src/backend/tests/unit/test_messages.py::test_aadd_messagetables": 7.735997641999802, - "src/backend/tests/unit/test_messages.py::test_add_messages": 7.782148285000403, + "src/backend/tests/unit/test_logger.py::test_enabled": 0.0005413090000274678, + "src/backend/tests/unit/test_logger.py::test_get_after_timestamp": 0.0005717149999782123, + "src/backend/tests/unit/test_logger.py::test_get_before_timestamp": 0.0005661840000357188, + "src/backend/tests/unit/test_logger.py::test_get_last_n": 0.0005405969998264482, + "src/backend/tests/unit/test_logger.py::test_init_default": 0.0005404059997999866, + "src/backend/tests/unit/test_logger.py::test_init_with_env_variable": 0.001028095000265239, + "src/backend/tests/unit/test_logger.py::test_len": 0.0005346059999737918, + "src/backend/tests/unit/test_logger.py::test_max_size": 0.0004961339998317271, + "src/backend/tests/unit/test_logger.py::test_write": 0.0005639709997922182, + "src/backend/tests/unit/test_logger.py::test_write_overflow": 0.000561235000304805, + "src/backend/tests/unit/test_login.py::test_login_successful": 1.5617708889999449, + "src/backend/tests/unit/test_login.py::test_login_unsuccessful_wrong_password": 1.5794934000000467, + "src/backend/tests/unit/test_login.py::test_login_unsuccessful_wrong_username": 1.5187884360000226, + "src/backend/tests/unit/test_messages.py::test_aadd_messages": 1.6231730080000943, + "src/backend/tests/unit/test_messages.py::test_aadd_messagetables": 1.6020565650001117, + "src/backend/tests/unit/test_messages.py::test_add_messages": 1.626520419000144, "src/backend/tests/unit/test_messages.py::test_add_messagetables": 0.05725845799315721, - "src/backend/tests/unit/test_messages.py::test_adelete_messages": 7.624223948000235, - "src/backend/tests/unit/test_messages.py::test_aget_messages": 7.701676045999648, - "src/backend/tests/unit/test_messages.py::test_astore_message": 7.690879489000054, - "src/backend/tests/unit/test_messages.py::test_aupdate_message_with_content_blocks": 7.633892253999875, - "src/backend/tests/unit/test_messages.py::test_aupdate_message_with_nested_properties": 7.6532730250000895, - "src/backend/tests/unit/test_messages.py::test_aupdate_message_with_timestamp": 7.937252523000097, - "src/backend/tests/unit/test_messages.py::test_aupdate_mixed_messages": 7.822734075999961, - "src/backend/tests/unit/test_messages.py::test_aupdate_multiple_messages": 7.83602666500019, - "src/backend/tests/unit/test_messages.py::test_aupdate_multiple_messages_with_timestamps": 7.68422044900035, + "src/backend/tests/unit/test_messages.py::test_adelete_messages": 1.5568391219999285, + "src/backend/tests/unit/test_messages.py::test_aget_messages": 1.521009597000102, + "src/backend/tests/unit/test_messages.py::test_astore_message": 1.6243206829999508, + "src/backend/tests/unit/test_messages.py::test_aupdate_message_with_content_blocks": 1.5972662259998742, + "src/backend/tests/unit/test_messages.py::test_aupdate_message_with_nested_properties": 1.602534328000047, + "src/backend/tests/unit/test_messages.py::test_aupdate_message_with_timestamp": 1.5871280220001154, + "src/backend/tests/unit/test_messages.py::test_aupdate_mixed_messages": 1.5728207469999234, + "src/backend/tests/unit/test_messages.py::test_aupdate_multiple_messages": 1.5900392140001713, + "src/backend/tests/unit/test_messages.py::test_aupdate_multiple_messages_with_timestamps": 1.5633066049999798, "src/backend/tests/unit/test_messages.py::test_aupdate_nonexistent_message": 3.133551847000035, - "src/backend/tests/unit/test_messages.py::test_aupdate_nonexistent_message_generates_a_new_message": 7.915576940999927, - "src/backend/tests/unit/test_messages.py::test_aupdate_single_message": 7.6297871970000415, - "src/backend/tests/unit/test_messages.py::test_convert_to_langchain[convert_to_langchain_type]": 0.0015151719999266788, - "src/backend/tests/unit/test_messages.py::test_convert_to_langchain[message]": 0.001754859999891778, - "src/backend/tests/unit/test_messages.py::test_delete_messages": 7.669362023999838, - "src/backend/tests/unit/test_messages.py::test_get_messages": 7.734136471000056, - "src/backend/tests/unit/test_messages.py::test_store_message": 7.6235474899999645, + "src/backend/tests/unit/test_messages.py::test_aupdate_nonexistent_message_generates_a_new_message": 1.5784494020001603, + "src/backend/tests/unit/test_messages.py::test_aupdate_single_message": 1.5570718739998028, + "src/backend/tests/unit/test_messages.py::test_convert_to_langchain[convert_to_langchain_type]": 0.0006909960000029969, + "src/backend/tests/unit/test_messages.py::test_convert_to_langchain[message]": 0.0008285330000035174, + "src/backend/tests/unit/test_messages.py::test_delete_messages": 1.579748290000225, + "src/backend/tests/unit/test_messages.py::test_get_messages": 1.5057488729999022, + "src/backend/tests/unit/test_messages.py::test_store_message": 1.5526250890000028, "src/backend/tests/unit/test_messages.py::test_update_message_with_content_blocks": 5.128578291973099, "src/backend/tests/unit/test_messages.py::test_update_message_with_nested_properties": 1.5983659149496816, "src/backend/tests/unit/test_messages.py::test_update_message_with_timestamp": 4.5035865410463884, @@ -1768,117 +1861,117 @@ "src/backend/tests/unit/test_messages.py::test_update_multiple_messages_with_timestamps": 4.659952084010001, "src/backend/tests/unit/test_messages.py::test_update_nonexistent_message": 4.162011249980424, "src/backend/tests/unit/test_messages.py::test_update_single_message": 8.01532608200796, - "src/backend/tests/unit/test_messages_endpoints.py::test_delete_messages": 7.686778545999459, - "src/backend/tests/unit/test_messages_endpoints.py::test_delete_messages_session": 7.640551324000171, - "src/backend/tests/unit/test_messages_endpoints.py::test_no_messages_found_with_given_session_id": 7.706243486999938, - "src/backend/tests/unit/test_messages_endpoints.py::test_successfully_update_session_id": 7.680804253000133, - "src/backend/tests/unit/test_messages_endpoints.py::test_update_message": 7.667970544000127, - "src/backend/tests/unit/test_messages_endpoints.py::test_update_message_not_found": 7.701843030999953, - "src/backend/tests/unit/test_process.py::test_load_langchain_object_with_cached_session": 0.008460845000172412, + "src/backend/tests/unit/test_messages_endpoints.py::test_delete_messages": 1.570630612999821, + "src/backend/tests/unit/test_messages_endpoints.py::test_delete_messages_session": 1.562733216999959, + "src/backend/tests/unit/test_messages_endpoints.py::test_no_messages_found_with_given_session_id": 1.5707609989999582, + "src/backend/tests/unit/test_messages_endpoints.py::test_successfully_update_session_id": 1.6426889639999445, + "src/backend/tests/unit/test_messages_endpoints.py::test_update_message": 1.5730772859999433, + "src/backend/tests/unit/test_messages_endpoints.py::test_update_message_not_found": 1.5553043039999466, + "src/backend/tests/unit/test_process.py::test_load_langchain_object_with_cached_session": 0.00427003199979481, "src/backend/tests/unit/test_process.py::test_load_langchain_object_with_no_cached_session": 2.9178847920848057, "src/backend/tests/unit/test_process.py::test_load_langchain_object_without_session_id": 2.8941064990358427, - "src/backend/tests/unit/test_process.py::test_multiple_tweaks": 0.0012274179998712498, - "src/backend/tests/unit/test_process.py::test_no_tweaks": 0.0014008619996275229, - "src/backend/tests/unit/test_process.py::test_single_tweak": 0.0012098649999643385, - "src/backend/tests/unit/test_process.py::test_tweak_no_node_id": 0.001187144999676093, - "src/backend/tests/unit/test_process.py::test_tweak_not_in_template": 0.001160683000307472, - "src/backend/tests/unit/test_schema.py::TestInput::test_field_type_str": 0.0012313159995755996, - "src/backend/tests/unit/test_schema.py::TestInput::test_field_type_type": 0.001201240000227699, - "src/backend/tests/unit/test_schema.py::TestInput::test_input_to_dict": 0.0012359340007606079, - "src/backend/tests/unit/test_schema.py::TestInput::test_invalid_field_type": 0.0012568340002871992, - "src/backend/tests/unit/test_schema.py::TestInput::test_post_process_type_function": 0.0017515250001451932, - "src/backend/tests/unit/test_schema.py::TestInput::test_serialize_field_type": 0.0011935749998883693, - "src/backend/tests/unit/test_schema.py::TestInput::test_validate_type_class": 0.0011882439998771588, - "src/backend/tests/unit/test_schema.py::TestInput::test_validate_type_string": 0.0011661250000543077, - "src/backend/tests/unit/test_schema.py::TestOutput::test_output_add_types": 0.0011512859996400948, - "src/backend/tests/unit/test_schema.py::TestOutput::test_output_default": 0.00119352399951822, + "src/backend/tests/unit/test_process.py::test_multiple_tweaks": 0.00042928999982905225, + "src/backend/tests/unit/test_process.py::test_no_tweaks": 0.0005511560000286408, + "src/backend/tests/unit/test_process.py::test_single_tweak": 0.00047094799992919434, + "src/backend/tests/unit/test_process.py::test_tweak_no_node_id": 0.000432736000220757, + "src/backend/tests/unit/test_process.py::test_tweak_not_in_template": 0.0004695339996487746, + "src/backend/tests/unit/test_schema.py::TestInput::test_field_type_str": 0.0005014840000967524, + "src/backend/tests/unit/test_schema.py::TestInput::test_field_type_type": 0.00045346399997470144, + "src/backend/tests/unit/test_schema.py::TestInput::test_input_to_dict": 0.000525487999766483, + "src/backend/tests/unit/test_schema.py::TestInput::test_invalid_field_type": 0.0004848519997722178, + "src/backend/tests/unit/test_schema.py::TestInput::test_post_process_type_function": 0.0008248369999819261, + "src/backend/tests/unit/test_schema.py::TestInput::test_serialize_field_type": 0.00044205200015312585, + "src/backend/tests/unit/test_schema.py::TestInput::test_validate_type_class": 0.0004621709999810264, + "src/backend/tests/unit/test_schema.py::TestInput::test_validate_type_string": 0.000455497999837462, + "src/backend/tests/unit/test_schema.py::TestOutput::test_output_add_types": 0.0004450289998203516, + "src/backend/tests/unit/test_schema.py::TestOutput::test_output_default": 0.00045572800013360393, "src/backend/tests/unit/test_schema.py::TestOutput::test_output_set_selected": 0.0011847680002574634, - "src/backend/tests/unit/test_schema.py::TestOutput::test_output_to_dict": 0.0012138729998696363, - "src/backend/tests/unit/test_schema.py::TestOutput::test_output_validate_display_name": 0.0012279900001885835, - "src/backend/tests/unit/test_schema.py::TestOutput::test_output_validate_model": 0.0012006980000478507, - "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_custom_type": 0.001190249000046606, - "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_int_type": 0.0011650319997897896, - "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_list_custom_type": 0.0011574980003388191, - "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_list_int_type": 0.0011399250001886685, - "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_union_custom_type": 0.001163820999863674, - "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_union_type": 0.0011547240001164027, - "src/backend/tests/unit/test_schema.py::test_schema_to_langflow_inputs": 0.002433519000078377, - "src/backend/tests/unit/test_schema.py::test_schema_to_langflow_inputs_invalid_type": 0.016408752000188542, - "src/backend/tests/unit/test_setup_superuser.py::test_teardown_superuser_default_superuser": 0.0027882379995389783, - "src/backend/tests/unit/test_setup_superuser.py::test_teardown_superuser_no_default_superuser": 0.0027922559997932694, - "src/backend/tests/unit/test_telemetry.py::test_gauge": 0.0011848989997815806, - "src/backend/tests/unit/test_telemetry.py::test_gauge_with_counter_method": 0.0013075780002509418, - "src/backend/tests/unit/test_telemetry.py::test_gauge_with_historgram_method": 0.0012719909996121714, - "src/backend/tests/unit/test_telemetry.py::test_gauge_with_up_down_counter_method": 0.0013094800006001606, - "src/backend/tests/unit/test_telemetry.py::test_increment_counter": 0.0012060989997735305, - "src/backend/tests/unit/test_telemetry.py::test_increment_counter_empty_label": 0.0012387090000629541, - "src/backend/tests/unit/test_telemetry.py::test_increment_counter_missing_mandatory_label": 0.0012787539999408182, - "src/backend/tests/unit/test_telemetry.py::test_increment_counter_unregisted_metric": 0.0013166249996174884, - "src/backend/tests/unit/test_telemetry.py::test_init": 0.0012681319999501284, - "src/backend/tests/unit/test_telemetry.py::test_missing_labels": 0.0012882010005341726, - "src/backend/tests/unit/test_telemetry.py::test_multithreaded_singleton": 0.006082127000354376, - "src/backend/tests/unit/test_telemetry.py::test_multithreaded_singleton_race_condition": 0.018960817999868596, - "src/backend/tests/unit/test_telemetry.py::test_opentelementry_singleton": 0.0012143540002398368, - "src/backend/tests/unit/test_template.py::test_build_template_from_function": 0.004162713000368967, - "src/backend/tests/unit/test_template.py::test_get_base_classes": 0.0011852689999614086, - "src/backend/tests/unit/test_template.py::test_get_default_factory": 0.0012487879994296236, - "src/backend/tests/unit/test_user.py::test_add_user": 7.795754034999845, - "src/backend/tests/unit/test_user.py::test_data_consistency_after_delete": 7.728943793999406, - "src/backend/tests/unit/test_user.py::test_data_consistency_after_update": 7.784702133999872, - "src/backend/tests/unit/test_user.py::test_deactivated_user_cannot_access": 7.778426885000044, - "src/backend/tests/unit/test_user.py::test_deactivated_user_cannot_login": 7.731014481999864, - "src/backend/tests/unit/test_user.py::test_delete_user": 7.73805262399992, - "src/backend/tests/unit/test_user.py::test_delete_user_wrong_id": 7.818076284999734, - "src/backend/tests/unit/test_user.py::test_inactive_user": 7.679848370999935, - "src/backend/tests/unit/test_user.py::test_normal_user_cant_delete_user": 8.988258837000558, - "src/backend/tests/unit/test_user.py::test_normal_user_cant_read_all_users": 7.817064240000491, - "src/backend/tests/unit/test_user.py::test_patch_reset_password": 15.103026480999688, - "src/backend/tests/unit/test_user.py::test_patch_user": 7.918753929999639, - "src/backend/tests/unit/test_user.py::test_patch_user_wrong_id": 7.782878516000437, - "src/backend/tests/unit/test_user.py::test_read_all_users": 7.860618053000053, - "src/backend/tests/unit/test_user.py::test_user_waiting_for_approval": 7.692121774999578, - "src/backend/tests/unit/test_validate_code.py::test_create_class": 0.0019449889996394631, - "src/backend/tests/unit/test_validate_code.py::test_create_class_module_import": 0.010028471000168793, - "src/backend/tests/unit/test_validate_code.py::test_create_class_with_external_variables_and_functions": 0.0017880060004245024, - "src/backend/tests/unit/test_validate_code.py::test_create_class_with_multiple_external_classes": 0.0019398690001253271, - "src/backend/tests/unit/test_validate_code.py::test_create_function": 0.0016753960003370594, - "src/backend/tests/unit/test_validate_code.py::test_execute_function_missing_function": 0.001422033999915584, - "src/backend/tests/unit/test_validate_code.py::test_execute_function_missing_module": 0.0016014380003070983, - "src/backend/tests/unit/test_validate_code.py::test_execute_function_missing_schema": 0.0016493780003656866, - "src/backend/tests/unit/test_validate_code.py::test_execute_function_success": 0.0013755770000898337, - "src/backend/tests/unit/test_validate_code.py::test_validate_code": 0.001780170999609254, - "src/backend/tests/unit/test_version.py::test_compute_main": 0.0012076729999535019, - "src/backend/tests/unit/test_version.py::test_version": 0.0012520949994723196, - "src/backend/tests/unit/test_voice_mode.py::test_resample_24k_to_16k_invalid_frame": 0.00128617900008976, - "src/backend/tests/unit/test_voice_mode.py::test_resample_24k_to_16k_valid_frame": 0.0016131309998854704, - "src/backend/tests/unit/test_voice_mode.py::test_webrtcvad_silence_detection": 0.0013049340000179654, - "src/backend/tests/unit/test_voice_mode.py::test_webrtcvad_with_real_data": 0.004043283000100928, - "src/backend/tests/unit/test_webhook.py::test_webhook_endpoint": 8.71781595099992, - "src/backend/tests/unit/test_webhook.py::test_webhook_flow_on_run_endpoint": 9.097450467999806, - "src/backend/tests/unit/test_webhook.py::test_webhook_with_random_payload": 9.586565992000033, - "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol::password@host-protocol::password@host]": 0.0012169910000920936, - "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user:pa:ss:word@host-protocol:user:pa:ss:word@host]": 0.001257186000202637, - "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user:pa@ss@word@host-protocol:user:pa%40ss%40word@host]": 0.001253006999831996, - "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user:pass@word@host-protocol:user:pass%40word@host]": 0.001309664000018529, - "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user:password@-protocol:user:password@]": 0.0012330800000199815, - "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user:password@host-protocol:user:password@host]": 0.0016584040004090639, - "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user@host-protocol:user@host]": 0.0012568249999276304, - "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[user:password@host-user:password@host]": 0.0012560139998640807, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[-]": 0.0012307560000408557, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/\\ndocu\\nments/file.txt-/home/user/\\\\ndocu\\\\nments/file.txt]": 0.0011967919999733567, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/docu\\n\\nments/file.txt-/home/user/docu\\\\n\\\\nments/file.txt]": 0.0012327400004323863, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/docu\\nments/file.txt-/home/user/docu\\\\nments/file.txt]": 0.0012216490003993385, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/documents/\\n-/home/user/documents/\\\\n]": 0.0012033449997943535, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/documents/file.txt-/home/user/documents/file.txt]": 0.0012515359999270004, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/my-\\ndocs/special_file!.pdf-/home/user/my-\\\\ndocs/special_file!.pdf]": 0.0012333209997450467, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[C:/Users\\\\Documents/file.txt-C:/Users\\\\Documents/file.txt]": 0.00122477600007187, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[C:\\\\Users\\\\Documents\\\\-C:\\\\Users\\\\Documents\\\\]": 0.001212522999594512, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[C:\\\\Users\\\\Documents\\\\file.txt-C:\\\\Users\\\\Documents\\\\file.txt]": 0.001234264000231633, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[C:\\\\Users\\\\\\nDocuments\\\\file.txt-C:\\\\Users\\\\\\\\nDocuments\\\\file.txt]": 0.00123551500018948, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[\\\\\\\\server\\\\share\\\\file.txt-\\\\\\\\server\\\\share\\\\file.txt]": 0.0012207380009385815, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[\\n/home/user/documents/-\\\\n/home/user/documents/]": 0.0011930449995816161, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[\\n\\n\\n-\\\\n\\\\n\\\\n]": 0.001567725999848335, - "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path_type": 0.0011501769999995304, + "src/backend/tests/unit/test_schema.py::TestOutput::test_output_to_dict": 0.00046446500005004054, + "src/backend/tests/unit/test_schema.py::TestOutput::test_output_validate_display_name": 0.0004624919999969279, + "src/backend/tests/unit/test_schema.py::TestOutput::test_output_validate_model": 0.000452873000085674, + "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_custom_type": 0.00045844299984310055, + "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_int_type": 0.0004145319999224739, + "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_list_custom_type": 0.00043424900036370673, + "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_list_int_type": 0.0004075189999639406, + "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_union_custom_type": 0.00045543800024461234, + "src/backend/tests/unit/test_schema.py::TestPostProcessType::test_union_type": 0.000462280999727227, + "src/backend/tests/unit/test_schema.py::test_schema_to_langflow_inputs": 0.0013725469998462358, + "src/backend/tests/unit/test_schema.py::test_schema_to_langflow_inputs_invalid_type": 0.012805617999902097, + "src/backend/tests/unit/test_setup_superuser.py::test_teardown_superuser_default_superuser": 0.0017061880000710516, + "src/backend/tests/unit/test_setup_superuser.py::test_teardown_superuser_no_default_superuser": 0.0017637439998452464, + "src/backend/tests/unit/test_telemetry.py::test_gauge": 0.0004893019997780357, + "src/backend/tests/unit/test_telemetry.py::test_gauge_with_counter_method": 0.0005358269997941534, + "src/backend/tests/unit/test_telemetry.py::test_gauge_with_historgram_method": 0.0005529099998966558, + "src/backend/tests/unit/test_telemetry.py::test_gauge_with_up_down_counter_method": 0.0005257489999621612, + "src/backend/tests/unit/test_telemetry.py::test_increment_counter": 0.00044447900017985376, + "src/backend/tests/unit/test_telemetry.py::test_increment_counter_empty_label": 0.0005211399998188426, + "src/backend/tests/unit/test_telemetry.py::test_increment_counter_missing_mandatory_label": 0.0005550729999868054, + "src/backend/tests/unit/test_telemetry.py::test_increment_counter_unregisted_metric": 0.0005106019998493139, + "src/backend/tests/unit/test_telemetry.py::test_init": 0.000495643000022028, + "src/backend/tests/unit/test_telemetry.py::test_missing_labels": 0.00048488199990970315, + "src/backend/tests/unit/test_telemetry.py::test_multithreaded_singleton": 0.004040254000074128, + "src/backend/tests/unit/test_telemetry.py::test_multithreaded_singleton_race_condition": 0.014790129999710189, + "src/backend/tests/unit/test_telemetry.py::test_opentelementry_singleton": 0.0004341280000517145, + "src/backend/tests/unit/test_template.py::test_build_template_from_function": 0.002369643999827531, + "src/backend/tests/unit/test_template.py::test_get_base_classes": 0.0005973530001028848, + "src/backend/tests/unit/test_template.py::test_get_default_factory": 0.0008350459997927828, + "src/backend/tests/unit/test_user.py::test_add_user": 1.5453698700000587, + "src/backend/tests/unit/test_user.py::test_data_consistency_after_delete": 1.7007222429999729, + "src/backend/tests/unit/test_user.py::test_data_consistency_after_update": 1.5802350319997913, + "src/backend/tests/unit/test_user.py::test_deactivated_user_cannot_access": 1.5652603390001332, + "src/backend/tests/unit/test_user.py::test_deactivated_user_cannot_login": 1.5544240360000003, + "src/backend/tests/unit/test_user.py::test_delete_user": 1.5622803819999262, + "src/backend/tests/unit/test_user.py::test_delete_user_wrong_id": 1.6730086800000663, + "src/backend/tests/unit/test_user.py::test_inactive_user": 1.6556528729997808, + "src/backend/tests/unit/test_user.py::test_normal_user_cant_delete_user": 1.601206970000021, + "src/backend/tests/unit/test_user.py::test_normal_user_cant_read_all_users": 1.6138499020000836, + "src/backend/tests/unit/test_user.py::test_patch_reset_password": 1.6583327119999467, + "src/backend/tests/unit/test_user.py::test_patch_user": 1.574212007999904, + "src/backend/tests/unit/test_user.py::test_patch_user_wrong_id": 1.6031740220000756, + "src/backend/tests/unit/test_user.py::test_read_all_users": 1.5590703959999246, + "src/backend/tests/unit/test_user.py::test_user_waiting_for_approval": 1.6497881830000551, + "src/backend/tests/unit/test_validate_code.py::test_create_class": 0.0009506310000233498, + "src/backend/tests/unit/test_validate_code.py::test_create_class_module_import": 0.0073427840000022115, + "src/backend/tests/unit/test_validate_code.py::test_create_class_with_external_variables_and_functions": 0.0009172190000299452, + "src/backend/tests/unit/test_validate_code.py::test_create_class_with_multiple_external_classes": 0.0009737119996771071, + "src/backend/tests/unit/test_validate_code.py::test_create_function": 0.0007507880000048317, + "src/backend/tests/unit/test_validate_code.py::test_execute_function_missing_function": 0.0005950679999386921, + "src/backend/tests/unit/test_validate_code.py::test_execute_function_missing_module": 0.0007244499997796083, + "src/backend/tests/unit/test_validate_code.py::test_execute_function_missing_schema": 0.0007697439998537448, + "src/backend/tests/unit/test_validate_code.py::test_execute_function_success": 0.0005940769999597251, + "src/backend/tests/unit/test_validate_code.py::test_validate_code": 0.0009196940000038012, + "src/backend/tests/unit/test_version.py::test_compute_main": 0.0004736809996757074, + "src/backend/tests/unit/test_version.py::test_version": 0.0004791139999724692, + "src/backend/tests/unit/test_voice_mode.py::test_resample_24k_to_16k_invalid_frame": 0.0005286040000100911, + "src/backend/tests/unit/test_voice_mode.py::test_resample_24k_to_16k_valid_frame": 0.0008294740000565071, + "src/backend/tests/unit/test_voice_mode.py::test_webrtcvad_silence_detection": 0.0005696410000837204, + "src/backend/tests/unit/test_voice_mode.py::test_webrtcvad_with_real_data": 0.002606885999966835, + "src/backend/tests/unit/test_webhook.py::test_webhook_endpoint": 1.6666376060002221, + "src/backend/tests/unit/test_webhook.py::test_webhook_flow_on_run_endpoint": 1.6210199150002609, + "src/backend/tests/unit/test_webhook.py::test_webhook_with_random_payload": 1.615853775999767, + "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol::password@host-protocol::password@host]": 0.00046758099983890133, + "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user:pa:ss:word@host-protocol:user:pa:ss:word@host]": 0.00047918199993546295, + "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user:pa@ss@word@host-protocol:user:pa%40ss%40word@host]": 0.0004931689998102229, + "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user:pass@word@host-protocol:user:pass%40word@host]": 0.0005271509999147383, + "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user:password@-protocol:user:password@]": 0.0004642020001028868, + "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user:password@host-protocol:user:password@host]": 0.0007660359999590582, + "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[protocol:user@host-protocol:user@host]": 0.0005260100001578394, + "src/backend/tests/unit/utils/test_connection_string_parser.py::test_transform_connection_string[user:password@host-user:password@host]": 0.0004944209997574944, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[-]": 0.00046209999982238514, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/\\ndocu\\nments/file.txt-/home/user/\\\\ndocu\\\\nments/file.txt]": 0.0004885700002432714, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/docu\\n\\nments/file.txt-/home/user/docu\\\\n\\\\nments/file.txt]": 0.00045711099983236636, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/docu\\nments/file.txt-/home/user/docu\\\\nments/file.txt]": 0.0004733319999559171, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/documents/\\n-/home/user/documents/\\\\n]": 0.00047968499984563095, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/documents/file.txt-/home/user/documents/file.txt]": 0.0004732410000087839, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[/home/user/my-\\ndocs/special_file!.pdf-/home/user/my-\\\\ndocs/special_file!.pdf]": 0.0004776099999617145, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[C:/Users\\\\Documents/file.txt-C:/Users\\\\Documents/file.txt]": 0.0004582840001603472, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[C:\\\\Users\\\\Documents\\\\-C:\\\\Users\\\\Documents\\\\]": 0.000478180000300199, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[C:\\\\Users\\\\Documents\\\\file.txt-C:\\\\Users\\\\Documents\\\\file.txt]": 0.00048181700026361796, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[C:\\\\Users\\\\\\nDocuments\\\\file.txt-C:\\\\Users\\\\\\\\nDocuments\\\\file.txt]": 0.000494000000117012, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[\\\\\\\\server\\\\share\\\\file.txt-\\\\\\\\server\\\\share\\\\file.txt]": 0.00047048700002960686, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[\\n/home/user/documents/-\\\\n/home/user/documents/]": 0.0004574520000915072, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path[\\n\\n\\n-\\\\n\\\\n\\\\n]": 0.00047298100025727763, + "src/backend/tests/unit/utils/test_format_directory_path.py::test_format_directory_path_type": 0.00041629599968473485, "src/backend/tests/unit/utils/test_image_utils.py::TestImageUtils::test_convert_image_to_base64_directory": 0.002373834024183452, "src/backend/tests/unit/utils/test_image_utils.py::TestImageUtils::test_convert_image_to_base64_empty_path": 0.0015134999412111938, "src/backend/tests/unit/utils/test_image_utils.py::TestImageUtils::test_convert_image_to_base64_nonexistent_file": 0.0014794580056332052, @@ -1887,74 +1980,74 @@ "src/backend/tests/unit/utils/test_image_utils.py::TestImageUtils::test_create_data_url_success": 0.0014539569965563715, "src/backend/tests/unit/utils/test_image_utils.py::TestImageUtils::test_create_data_url_unrecognized_extension": 0.0038709990330971777, "src/backend/tests/unit/utils/test_image_utils.py::TestImageUtils::test_create_data_url_with_custom_mime": 0.0027264999807812274, - "src/backend/tests/unit/utils/test_image_utils.py::test_convert_image_to_base64_directory": 0.0017543230001138, - "src/backend/tests/unit/utils/test_image_utils.py::test_convert_image_to_base64_empty_path": 0.0012473880001380167, - "src/backend/tests/unit/utils/test_image_utils.py::test_convert_image_to_base64_nonexistent_file": 0.001262225000118633, - "src/backend/tests/unit/utils/test_image_utils.py::test_convert_image_to_base64_success": 0.001938397000230907, - "src/backend/tests/unit/utils/test_image_utils.py::test_create_data_url_invalid_file": 0.0012083540000276116, - "src/backend/tests/unit/utils/test_image_utils.py::test_create_data_url_success": 0.0019073180001214496, - "src/backend/tests/unit/utils/test_image_utils.py::test_create_data_url_unrecognized_extension": 0.001817200999994384, - "src/backend/tests/unit/utils/test_image_utils.py::test_create_data_url_with_custom_mime": 0.001875980999557214, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[-]": 0.0012129549995734124, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/\\ndocu\\nments/file.txt-/home/user/\\\\ndocu\\\\nments/file.txt]": 0.001234433999798057, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/docu\\n\\nments/file.txt-/home/user/docu\\\\n\\\\nments/file.txt]": 0.0011989969998467132, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/docu\\nments/file.txt-/home/user/docu\\\\nments/file.txt]": 0.0012198959998386272, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/documents/\\n-/home/user/documents/\\\\n]": 0.0012212789997647633, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/documents/file.txt-/home/user/documents/file.txt]": 0.0012102479995519388, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/my-\\ndocs/special_file!.pdf-/home/user/my-\\\\ndocs/special_file!.pdf]": 0.0012137439994148735, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[C:\\\\Users\\\\\\nDocuments\\\\file.txt-C:\\\\Users\\\\\\\\nDocuments\\\\file.txt]": 0.0012195360000077926, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[\\n/home/user/documents/-\\\\n/home/user/documents/]": 0.0012198469999020745, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[\\n\\n\\n-\\\\n\\\\n\\\\n]": 0.0012043379992974224, - "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path_type": 0.00113768200026243, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_negative_max_length": 0.0014687920001961174, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[-5-]": 0.0012406060000103025, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[12345-3-12345]": 0.001208394000059343, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[3.141592653589793-4-3.141592653589793]": 0.0012627770006474748, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[None-5-None]": 0.0012488599995776895, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[True-2-True]": 0.0012466780003705935, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[\\u3053\\u3093\\u306b\\u3061\\u306f-3-\\u3053\\u3093\\u306b...]": 0.0012260070002412249, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[a-1-a]": 0.0012407560002429818, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-10-aaaaaaaaaa...]": 0.0012353150000308233, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[exact-5-exact]": 0.0012311170003158622, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[long string-7-long st...]": 0.0012328299999353476, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[short string-20-short string]": 0.0012541000000965141, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_none_max_length": 0.0011385160000827454, - "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_zero_max_length": 0.001196861999687826, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data0-10-expected0]": 0.0012440599998626567, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data1-5-expected1]": 0.001251594999757799, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data2-7-expected2]": 0.0012388419995659206, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data3-8-expected3]": 0.0012449930000002496, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data4-10-expected4]": 0.0012382900004013209, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data5-10-expected5]": 0.0012268290001884452, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data6-10-expected6]": 0.0014056820000405423, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data7-5-expected7]": 0.0013286490002428764, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data8-3-expected8]": 0.0013027210002292122, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data9-10-expected9]": 0.0018001989992626477, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_default_max_length": 0.0011950300004173187, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_in_place_modification": 0.0012186239996481163, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_invalid_input": 0.0011820949998764263, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_negative_max_length": 0.001123476999509876, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_no_modification": 0.0011917739998352772, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_small_max_length": 0.0011262729994996334, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_type_preservation": 0.0011940679996769177, - "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_zero_max_length": 0.0011577499994928075, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[ invalid -False]": 0.0012489610003285634, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[-False]": 0.0012423090001902892, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[None-False]": 0.001182897000489902, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[invalid://:@/test-False]": 0.0313481490002232, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[invalid://database-False]": 0.03173566199984634, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[mysql+mysqldb://scott:tiger@localhost/foo-True]": 0.0016342190001523704, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[mysql+pymysql://scott:tiger@localhost/foo-True]": 0.0013264949998301745, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[mysql://user:pass@localhost/dbname-True]": 0.05084469600024022, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[not_a_url-False]": 0.0012120710007366142, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[oracle+cx_oracle://scott:tiger@tnsalias-True]": 0.0013752159998148272, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[oracle+oracledb://scott:tiger@127.0.0.1:1521/?service_name=freepdb1-True]": 0.0013126290000400331, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[oracle://scott:tiger@127.0.0.1:1521/?service_name=freepdb1-True]": 0.04604546100017615, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[postgresql+pg8000://dbuser:kx%40jj5%2Fg@pghost10/appdb-True]": 0.001275690000056784, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[postgresql+psycopg2://scott:tiger@localhost:5432/mydatabase-True]": 0.0012745980002364377, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[postgresql://user:pass@localhost/dbname-True]": 0.0012192850003884814, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[sqlite+aiosqlite:////var/folders/test.db-True]": 0.0012265179993846687, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[sqlite:////var/folders/test.db-True]": 0.0012261069996384322, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[sqlite:///:memory:-True]": 0.0012371490001896746, - "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[sqlite:///test.db-True]": 0.001238158999967709 + "src/backend/tests/unit/utils/test_image_utils.py::test_convert_image_to_base64_directory": 0.0008961589999216812, + "src/backend/tests/unit/utils/test_image_utils.py::test_convert_image_to_base64_empty_path": 0.0005363479997413378, + "src/backend/tests/unit/utils/test_image_utils.py::test_convert_image_to_base64_nonexistent_file": 0.0005271009997613874, + "src/backend/tests/unit/utils/test_image_utils.py::test_convert_image_to_base64_success": 0.0009685229997558054, + "src/backend/tests/unit/utils/test_image_utils.py::test_create_data_url_invalid_file": 0.0004805440000836825, + "src/backend/tests/unit/utils/test_image_utils.py::test_create_data_url_success": 0.0009807060000639467, + "src/backend/tests/unit/utils/test_image_utils.py::test_create_data_url_unrecognized_extension": 0.0009931800000231306, + "src/backend/tests/unit/utils/test_image_utils.py::test_create_data_url_with_custom_mime": 0.0009269769998354604, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[-]": 0.0004819080002107512, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/\\ndocu\\nments/file.txt-/home/user/\\\\ndocu\\\\nments/file.txt]": 0.00047758899995642423, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/docu\\n\\nments/file.txt-/home/user/docu\\\\n\\\\nments/file.txt]": 0.00047438199976568285, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/docu\\nments/file.txt-/home/user/docu\\\\nments/file.txt]": 0.00047016600001370534, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/documents/\\n-/home/user/documents/\\\\n]": 0.0004628819999652478, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/documents/file.txt-/home/user/documents/file.txt]": 0.0004739009998502297, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[/home/user/my-\\ndocs/special_file!.pdf-/home/user/my-\\\\ndocs/special_file!.pdf]": 0.0004770079999616428, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[C:\\\\Users\\\\\\nDocuments\\\\file.txt-C:\\\\Users\\\\\\\\nDocuments\\\\file.txt]": 0.000475376000167671, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[\\n/home/user/documents/-\\\\n/home/user/documents/]": 0.00047444399979212903, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path[\\n\\n\\n-\\\\n\\\\n\\\\n]": 0.0004629619998013368, + "src/backend/tests/unit/utils/test_rewrite_file_path.py::test_format_directory_path_type": 0.0004028000000744214, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_negative_max_length": 0.0004159750001235807, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[-5-]": 0.0004776390001097752, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[12345-3-12345]": 0.0004760350002470659, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[3.141592653589793-4-3.141592653589793]": 0.0004903729998204653, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[None-5-None]": 0.0004966639999111067, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[True-2-True]": 0.0005055809999703342, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[\\u3053\\u3093\\u306b\\u3061\\u306f-3-\\u3053\\u3093\\u306b...]": 0.00047522499971819343, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[a-1-a]": 0.00047779000010450545, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-10-aaaaaaaaaa...]": 0.000488809999978912, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[exact-5-exact]": 0.0004790730001786869, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[long string-7-long st...]": 0.0005020349999540485, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_non_dict_list[short string-20-short string]": 0.0005084360000182642, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_none_max_length": 0.000436272000115423, + "src/backend/tests/unit/utils/test_truncate_long_strings.py::test_truncate_long_strings_zero_max_length": 0.0004053530001328909, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data0-10-expected0]": 0.0005529120001028787, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data1-5-expected1]": 0.00051226300001872, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data2-7-expected2]": 0.0005024060001233011, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data3-8-expected3]": 0.00047718999985590926, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data4-10-expected4]": 0.0004739519997656316, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data5-10-expected5]": 0.0004997219998585933, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data6-10-expected6]": 0.00048769800014270004, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data7-5-expected7]": 0.0005070659999546479, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data8-3-expected8]": 0.0005148590000771947, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings[input_data9-10-expected9]": 0.0009225270000570163, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_default_max_length": 0.00041341999985888833, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_in_place_modification": 0.00043452800014165405, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_invalid_input": 0.00044758400008504395, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_negative_max_length": 0.0004504880000695266, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_no_modification": 0.0004007059999366902, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_small_max_length": 0.0004381560002002516, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_type_preservation": 0.00044129200000497804, + "src/backend/tests/unit/utils/test_truncate_long_strings_on_objects.py::test_truncate_long_strings_zero_max_length": 0.00041411100005461776, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[ invalid -False]": 0.0005507260000285896, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[-False]": 0.0005591910003204248, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[None-False]": 0.0005437229999643023, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[invalid://:@/test-False]": 0.019233800999927553, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[invalid://database-False]": 0.019437509999988833, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[mysql+mysqldb://scott:tiger@localhost/foo-True]": 0.0006006790001720219, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[mysql+pymysql://scott:tiger@localhost/foo-True]": 0.0005947680001554545, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[mysql://user:pass@localhost/dbname-True]": 0.039400988000124926, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[not_a_url-False]": 0.000547138999991148, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[oracle+cx_oracle://scott:tiger@tnsalias-True]": 0.0006219090000740835, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[oracle+oracledb://scott:tiger@127.0.0.1:1521/?service_name=freepdb1-True]": 0.0006004080000820977, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[oracle://scott:tiger@127.0.0.1:1521/?service_name=freepdb1-True]": 0.03693678899981023, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[postgresql+pg8000://dbuser:kx%40jj5%2Fg@pghost10/appdb-True]": 0.0005839880000166886, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[postgresql+psycopg2://scott:tiger@localhost:5432/mydatabase-True]": 0.0005089679998491192, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[postgresql://user:pass@localhost/dbname-True]": 0.0004886599999736063, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[sqlite+aiosqlite:////var/folders/test.db-True]": 0.0004856150001160131, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[sqlite:////var/folders/test.db-True]": 0.0005075360002138041, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[sqlite:///:memory:-True]": 0.0004889300003014796, + "src/backend/tests/unit/utils/test_util_strings.py::test_is_valid_database_url[sqlite:///test.db-True]": 0.0005179740001040045 } \ No newline at end of file