From 377f1791582d620849e4cf693fa114ad4646cdc8 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 1 Aug 2024 16:58:25 -0300 Subject: [PATCH] refactor: add getters and setters for inputs and outputs (#3119) * refactor: update code references to use _code instead of code * refactor: add backwards compatible attributes to Component class * refactor: update Component constructor to pass config params with underscore Refactored the `Component` class in `component.py` to handle inputs and outputs. Added a new method `map_outputs` to map a list of outputs to the component. Also updated the `__init__` method to properly initialize the inputs, outputs, and other attributes. This change improves the flexibility and extensibility of the `Component` class. Co-authored-by: Gabriel Luiz Freitas Almeida * refactor: change attribute to use underscore * refactor: update CustomComponent initialization parameters Refactored the `instantiate_class` function in `loading.py` to update the initialization parameters for the `CustomComponent` class. Changed the parameter names from `user_id`, `parameters`, `vertex`, and `tracing_service` to `_user_id`, `_parameters`, `_vertex`, and `_tracing_service` respectively. This change ensures consistency and improves code readability. Co-authored-by: Gabriel Luiz Freitas Almeida * refactor: update BaseComponent to accept UUID for _user_id Updated the `BaseComponent` class in `base_component.py` to accept a `UUID` type for the `_user_id` attribute. This change improves the type safety and ensures consistency with the usage of `_user_id` throughout the codebase. * refactor: import nanoid with type annotation The `nanoid` import in `component.py` has been updated to include a type annotation `# type: ignore`. This change ensures that the type checker ignores any errors related to the `nanoid` import. * fix(custom_component.py): convert _user_id to string before passing to functions to ensure compatibility with function signatures * feat(component.py): add method to set output types based on method return type to improve type checking and validation in custom components * refactor: extract method to get method return type in CustomComponent * refactor(utils.py): refactor code to use _user_id instead of user_id for consistency and clarity perf(utils.py): optimize code by reusing cc_instance instead of calling get_component_instance multiple times * refactor(utils.py, base.py): change parameter name 'add_name' to 'keep_name' for clarity and consistency in codebase * [autofix.ci] apply automated fixes * refactor: update schema.py to include Edge related typres The `schema.py` file in the `src/backend/base/langflow/graph/edge` directory has been updated to include the `TargetHandle` and `SourceHandle` models. These models define the structure and attributes of the target and source handles used in the edge data. This change improves the clarity and consistency of the codebase. * refactor: update BaseInputMixin to handle invalid field types gracefully The `BaseInputMixin` class in `input_mixin.py` has been updated to handle invalid field types gracefully. Instead of raising an exception, it now returns `FieldTypes.OTHER` for any invalid field type. This change improves the robustness and reliability of the codebase. * refactor: update file_types field alias in FileMixin The `file_types` field in the `FileMixin` class of `input_mixin.py` has been updated to use the `alias` parameter instead of `serialization_alias`. This change ensures consistency and improves the clarity of the codebase. * refactor(inputs): update field_type declarations in various input classes to use SerializableFieldTypes enum for better type safety and clarity * refactor(inputs): convert dict to Message object in _validate_value method * refactor(inputs): convert dict to Message object in _validate_value method * refactor(inputs): update model_config in BaseInputMixin to enable populating by name The `model_config` attribute in the `BaseInputMixin` class of `input_mixin.py` has been updated to include the `populate_by_name=True` parameter. This change allows the model configuration to be populated by name, improving the flexibility and usability of the codebase. * refactor: update _extract_return_type method in CustomComponent to accept Any type The _extract_return_type method in CustomComponent has been updated to accept the Any type as the return_type parameter. This change improves the flexibility and compatibility of the method, allowing it to handle a wider range of return types. * refactor(component): add get_input and get_output methods for easier access to input and output values The `Component` class in `component.py` has been updated to include the `get_input` and `get_output` methods. These methods allow for easier retrieval of input and output values by name, improving the usability and readability of the codebase. * refactor(vertex): add get_input and get_output methods for easier access to input and output values * refactor(component): add set_output_value method for easier modification of output values The `Component` class in `component.py` has been updated to include the `set_output_value` method. This method allows for easier modification of output values by name, improving the usability and flexibility of the codebase. * refactor: update BaseComponent to use get_template_config method Refactored the `BaseComponent` class in `base_component.py` to use the `get_template_config` method instead of duplicating the code. This change improves code readability and reduces redundancy. * feat: add BaseModel class with model_config attribute A new `BaseModel` class has been added to the `base_model.py` file. This class extends the `PydanticBaseModel` and includes a `model_config` attribute of type `ConfigDict`. This change improves the codebase by providing a base model with a configuration dictionary for models. Co-authored-by: Gabriel Luiz Freitas Almeida * refactor: update langflow.graph.edge.schema.py Refactor the `langflow.graph.edge.schema.py` file to include the `TargetHandle` and `SourceHandle` models. This change improves the clarity and consistency of the codebase. Co-authored-by: Gabriel Luiz Freitas Almeida * refactor: update build_custom_component_template to use add_name instead of keep_name Refactor the `build_custom_component_template` function in `utils.py` to use the `add_name` parameter instead of the deprecated `keep_name` parameter. This change ensures consistency with the updated method signature and improves code clarity. * feat(component.py): add method to set output types based on method return type to improve type checking and validation in custom components (#3115) * feat(component.py): add method to set output types based on method return type to improve type checking and validation in custom components * refactor: extract method to get method return type in CustomComponent * refactor: update _extract_return_type method in CustomComponent to accept Any type The _extract_return_type method in CustomComponent has been updated to accept the Any type as the return_type parameter. This change improves the flexibility and compatibility of the method, allowing it to handle a wider range of return types. * refactor: add _template_config property to BaseComponent Add a new `_template_config` property to the `BaseComponent` class in `base_component.py`. This property is used to store the template configuration for the custom component. If the `_template_config` property is empty, it is populated by calling the `build_template_config` method. This change improves the efficiency of accessing the template configuration and ensures that it is only built when needed. * refactor: add type checking for Output types in add_types method Improve type checking in the `add_types` method of the `Output` class in `base.py`. Check if the `type_` already exists in the `types` list before adding it. This change ensures that duplicate types are not added to the list. * update starter projects * refactor: optimize imports in base.py Optimize imports in the `base.py` file by removing unused imports and organizing the remaining imports. This change improves code readability and reduces unnecessary clutter. * fix(base.py): fix condition to check if self.types is not None before checking if type_ is in self.types * refactor: update build_custom_component_template to use add_name instead of keep_name * feat: update logger warning message for invalid value type in StrInput * refactor: update logger warning message for invalid value type in StrInput * refactor: add unit tests for inputs in test_inputs.py * refactor: update validation for IntInput value type Improve the validation for the value type in the IntInput class. The updated code ensures that the value is of a valid type (int or float) and converts float values to integers. This change enhances the accuracy and reliability of the input validation process. * refactor: improve validation for FloatInput value type Improve the validation for the value type in the FloatInput class. The updated code ensures that the value is of a valid type (int or float) and converts integer values to floats. This change enhances the accuracy and reliability of the input validation process. * fix(data.py): add validation to check if data is a dictionary before processing to prevent potential errors * refactor: update test_inputs.py to include comprehensive unit tests for input classes Add comprehensive unit tests for the input classes in the test_inputs.py file. This change ensures that the input classes are thoroughly tested and functioning correctly. The unit tests cover various scenarios and edge cases to validate the behavior of the input classes. This improvement enhances the reliability and stability of the codebase. * refactor: remove invalid input tests for DataInput and FileInput in test_inputs.py Cleaned up unnecessary test cases for invalid input types * refactor: improve validation for IntInput and FloatInput value types * refactor: add async version of get_file_content_dicts method in Message class --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../custom/custom_component/component.py | 34 +++++++++++++++++++ .../base/langflow/graph/vertex/types.py | 13 ++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/backend/base/langflow/custom/custom_component/component.py b/src/backend/base/langflow/custom/custom_component/component.py index a5373b449..4af5f65b8 100644 --- a/src/backend/base/langflow/custom/custom_component/component.py +++ b/src/backend/base/langflow/custom/custom_component/component.py @@ -89,6 +89,40 @@ class Component(CustomComponent): raise ValueError("Output name cannot be None.") self._outputs[output.name] = output + def get_input(self, name: str) -> Any: + """ + Retrieves the value of the input with the specified name. + Args: + name (str): The name of the input. + Returns: + Any: The value of the input. + Raises: + ValueError: If the input with the specified name is not found. + """ + if name in self._inputs: + return self._inputs[name] + raise ValueError(f"Input {name} not found in {self.__class__.__name__}") + + def get_output(self, name: str) -> Any: + """ + Retrieves the output with the specified name. + Args: + name (str): The name of the output to retrieve. + Returns: + Any: The output value. + Raises: + ValueError: If the output with the specified name is not found. + """ + if name in self._outputs: + return self._outputs[name] + raise ValueError(f"Output {name} not found in {self.__class__.__name__}") + + def set_output_value(self, name: str, value: Any): + if name in self._outputs: + self._outputs[name].value = value + else: + raise ValueError(f"Output {name} not found in {self.__class__.__name__}") + def validate(self, params: dict): self._validate_inputs(params) self._validate_outputs() diff --git a/src/backend/base/langflow/graph/vertex/types.py b/src/backend/base/langflow/graph/vertex/types.py index c36487dd9..2078e341c 100644 --- a/src/backend/base/langflow/graph/vertex/types.py +++ b/src/backend/base/langflow/graph/vertex/types.py @@ -9,11 +9,12 @@ from loguru import logger from langflow.graph.schema import CHAT_COMPONENTS, RECORDS_COMPONENTS, InterfaceComponentTypes, ResultData from langflow.graph.utils import UnbuiltObject, log_transaction, log_vertex_build, serialize_field from langflow.graph.vertex.base import Vertex +from langflow.inputs.inputs import InputTypes from langflow.schema import Data from langflow.schema.artifact import ArtifactType from langflow.schema.message import Message from langflow.schema.schema import INPUT_FIELD_NAME -from langflow.template.field.base import UNDEFINED +from langflow.template.field.base import UNDEFINED, Output from langflow.utils.schemas import ChatOutputResponse, DataOutputResponse from langflow.utils.util import unescape_string @@ -57,6 +58,16 @@ class ComponentVertex(Vertex): for key, value in self._built_object.items(): self.add_result(key, value) + def get_input(self, name: str) -> InputTypes: + if self._custom_component is None: + raise ValueError(f"Vertex {self.id} does not have a component instance.") + return self._custom_component.get_input(name) + + def get_output(self, name: str) -> Output: + if self._custom_component is None: + raise ValueError(f"Vertex {self.id} does not have a component instance.") + return self._custom_component.get_output(name) + def get_edge_with_target(self, target_id: str) -> Generator["ContractEdge", None, None]: """ Get the edge with the target id.