diff --git a/src/backend/langflow/interface/custom/utils.py b/src/backend/langflow/interface/custom/utils.py index af21e72c3..c377a1c96 100644 --- a/src/backend/langflow/interface/custom/utils.py +++ b/src/backend/langflow/interface/custom/utils.py @@ -17,7 +17,9 @@ from langflow.interface.custom.directory_reader.utils import ( ) from langflow.interface.importing.utils import eval_custom_component_code from langflow.template.field.base import TemplateField -from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode +from langflow.template.frontend_node.custom_components import ( + CustomComponentFrontendNode, +) from langflow.utils.util import get_base_classes from loguru import logger @@ -121,7 +123,7 @@ def add_new_custom_field( ): # Check field_config if any of the keys are in it # if it is, update the value - display_name = field_config.pop("display_name", field_name) + display_name = field_config.pop("display_name", None) field_type = field_config.pop("field_type", field_type) field_contains_list = "list" in field_type.lower() field_type = process_type(field_type) @@ -187,7 +189,11 @@ def get_field_dict(field: Union[TemplateField, dict]): return field -def run_build_config(custom_component: CustomComponent, user_id: Optional[Union[str, UUID]] = None, update_field=None): +def run_build_config( + custom_component: CustomComponent, + user_id: Optional[Union[str, UUID]] = None, + update_field=None, +): """Build the field configuration for a custom component""" try: @@ -376,7 +382,16 @@ def update_field_dict(field_dict): def sanitize_field_config(field_config: Dict): # If any of the already existing keys are in field_config, remove them - for key in ["name", "field_type", "value", "required", "placeholder", "display_name", "advanced", "show"]: + for key in [ + "name", + "field_type", + "value", + "required", + "placeholder", + "display_name", + "advanced", + "show", + ]: field_config.pop(key, None) return field_config diff --git a/src/backend/langflow/template/field/base.py b/src/backend/langflow/template/field/base.py index 021c0104d..798d07b55 100644 --- a/src/backend/langflow/template/field/base.py +++ b/src/backend/langflow/template/field/base.py @@ -1,8 +1,7 @@ from typing import Any, Callable, Optional, Union -from pydantic import BaseModel, ConfigDict, Field, field_serializer - from langflow.field_typing.range_spec import RangeSpec +from pydantic import BaseModel, ConfigDict, Field, field_serializer class TemplateField(BaseModel): @@ -64,6 +63,9 @@ class TemplateField(BaseModel): range_spec: Optional[RangeSpec] = Field(default=None, serialization_alias="rangeSpec") """Range specification for the field. Defaults to None.""" + title_case: bool = True + """Specifies if the field should be displayed in title case. Defaults to True.""" + def to_dict(self): return self.model_dump(by_alias=True, exclude_none=True) @@ -76,3 +78,15 @@ class TemplateField(BaseModel): if value == "float" and self.range_spec is None: self.range_spec = RangeSpec() return value + + @field_serializer("display_name") + def serialize_display_name(self, value, _info): + # If display_name is not set, use name and convert to title case + # if title_case is True + if value is None: + # name is probably a snake_case string + # Ex: "file_path" -> "File Path" + value = self.name.replace("_", " ") + if self.title_case: + value = value.title() + return value