🐛 fix(base.py): import UtilitiesFrontendNode from the correct module

 feat(base.py): add support for SQLDatabase utility and filter utilities according to settings.utilities
🎨 style(frontend_node/base.py): add display_name to fields
🎨 style(frontend_node/utilities.py): format field values and types
The import statement for UtilitiesFrontendNode was incorrect, causing an import error. The import statement was corrected to import from the correct module.

Support for SQLDatabase utility was added to the type_to_loader_dict dictionary. The dictionary is now filtered according to the settings.utilities list.

The display_name attribute was added to fields in the FrontendNode class to improve the readability of the frontend.

The format_field method in the UtilitiesFrontendNode class was updated to format field values and types. The method now converts field.field_type to a list if it is a Literal type and formats field.value if it is a dictionary.
This commit is contained in:
Gabriel Almeida 2023-05-27 16:32:56 -03:00
commit cc785af652
3 changed files with 57 additions and 10 deletions

View file

@ -1,26 +1,53 @@
from typing import Dict, List, Optional
from typing import Dict, List, Optional, Type
from langflow.custom.customs import get_custom_nodes
from langflow.interface.base import LangChainTypeCreator
from langflow.interface.custom_lists import utility_type_to_cls_dict
from langflow.interface.importing.utils import import_class
from langflow.settings import settings
from langflow.template.frontend_node.utilities import UtilitiesFrontendNode
from langflow.utils.logger import logger
from langflow.utils.util import build_template_from_class
from langchain import utilities, SQLDatabase
class UtilityCreator(LangChainTypeCreator):
type_name: str = "utilities"
@property
def frontend_node_class(self) -> Type[UtilitiesFrontendNode]:
return UtilitiesFrontendNode
@property
def type_to_loader_dict(self) -> Dict:
return utility_type_to_cls_dict
"""
Returns a dictionary mapping utility names to their corresponding loader classes.
If the dictionary has not been created yet, it is created by importing all utility classes
from the langchain.chains module and filtering them according to the settings.utilities list.
"""
if self.type_dict is None:
self.type_dict = {
utility_name: import_class(f"langchain.utilities.{utility_name}")
for utility_name in utilities.__all__
}
self.type_dict["SQLDatabase"] = SQLDatabase
# Filter according to settings.utilities
self.type_dict = {
name: utility
for name, utility in self.type_dict.items()
if name in settings.utilities or settings.dev
}
return self.type_dict
def get_signature(self, name: str) -> Optional[Dict]:
"""Get the signature of a utility."""
try:
if name in get_custom_nodes(self.type_name).keys():
return get_custom_nodes(self.type_name)[name]
return build_template_from_class(name, utility_type_to_cls_dict)
custom_nodes = get_custom_nodes(self.type_name)
if name in custom_nodes.keys():
return custom_nodes[name]
return build_template_from_class(name, self.type_to_loader_dict)
except ValueError as exc:
raise ValueError(f"Utility {name} not found") from exc
@ -29,11 +56,7 @@ class UtilityCreator(LangChainTypeCreator):
return None
def to_list(self) -> List[str]:
return [
utility.__name__
for utility in self.type_to_loader_dict.values()
if utility.__name__ in settings.utilities or settings.dev
]
return list(self.type_to_loader_dict.keys())
utility_creator = UtilityCreator()

View file

@ -143,6 +143,9 @@ class FrontendNode(BaseModel):
field.required = False
field.advanced = False
field.display_name = key.replace("_", " ").title()
field.display_name = field.display_name.replace("Api", "API")
@staticmethod
def should_show_field(key: str, required: bool) -> bool:
"""Determines whether the field should be shown."""

View file

@ -0,0 +1,21 @@
import json
from typing import Optional
from langflow.template.field.base import TemplateField
from langflow.template.frontend_node.base import FrontendNode
class UtilitiesFrontendNode(FrontendNode):
@staticmethod
def format_field(field: TemplateField, name: Optional[str] = None) -> None:
FrontendNode.format_field(field, name)
# field.field_type could be "Literal['news', 'search', 'places', 'images']
# we need to convert it to a list
if "Literal" in field.field_type:
field.options = eval(field.field_type.replace("Literal", ""))
field.is_list = True
field.field_type = "str"
if isinstance(field.value, dict):
field.field_type = "code"
field.value = json.dumps(field.value, indent=4)