From fa3bcdefee557add1b7e27b2d3fad179996233ae Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 29 Jun 2023 12:55:58 -0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=A6=20chore(output=5Fparsers):=20add?= =?UTF-8?q?=20output=20parsers=20module=20and=20base=20classes=20?= =?UTF-8?q?=F0=9F=9A=80=20feat(output=5Fparsers):=20add=20OutputParserCrea?= =?UTF-8?q?tor=20class=20to=20handle=20creation=20and=20loading=20of=20out?= =?UTF-8?q?put=20parsers=20=F0=9F=9A=80=20feat(output=5Fparsers):=20add=20?= =?UTF-8?q?OutputParserFrontendNode=20class=20to=20handle=20formatting=20o?= =?UTF-8?q?f=20output=20parser=20fields=20The=20commit=20adds=20the=20foll?= =?UTF-8?q?owing=20changes:=20-=20A=20new=20file=20`=5F=5Finit=5F=5F.py`?= =?UTF-8?q?=20is=20added=20to=20the=20`output=5Fparsers`=20module.=20-=20A?= =?UTF-8?q?=20new=20file=20`base.py`=20is=20added=20to=20the=20`output=5Fp?= =?UTF-8?q?arsers`=20module.=20-=20A=20new=20file=20`output=5Fparsers.py`?= =?UTF-8?q?=20is=20added=20to=20the=20`frontend=5Fnode`=20module.=20The=20?= =?UTF-8?q?`=5F=5Finit=5F=5F.py`=20file=20initializes=20the=20`OutputParse?= =?UTF-8?q?rCreator`=20class,=20which=20is=20responsible=20for=20creating?= =?UTF-8?q?=20and=20loading=20output=20parsers.=20It=20also=20defines=20a?= =?UTF-8?q?=20method=20to=20get=20the=20signature=20of=20an=20output=20par?= =?UTF-8?q?ser.=20The=20`base.py`=20file=20contains=20the=20base=20class?= =?UTF-8?q?=20`OutputParserCreator`=20which=20is=20a=20subclass=20of=20`La?= =?UTF-8?q?ngChainTypeCreator`.=20It=20defines=20the=20type=20name=20as=20?= =?UTF-8?q?"output=5Fparsers"=20and=20provides=20methods=20to=20get=20the?= =?UTF-8?q?=20frontend=20node=20class=20and=20the=20type=20to=20loader=20d?= =?UTF-8?q?ictionary.=20It=20also=20defines=20a=20method=20to=20convert=20?= =?UTF-8?q?the=20output=20parsers=20to=20a=20list.=20The=20`output=5Fparse?= =?UTF-8?q?rs.py`=20file=20contains=20the=20`OutputParserFrontendNode`=20c?= =?UTF-8?q?lass,=20which=20is=20a=20subclass=20of=20`FrontendNode`.=20It?= =?UTF-8?q?=20provides=20a=20method=20to=20format=20the=20field=20of=20an?= =?UTF-8?q?=20output=20parser.=20These=20changes=20are=20done=20to=20add?= =?UTF-8?q?=20support=20for=20output=20parsers=20in=20the=20application.?= =?UTF-8?q?=20The=20`OutputParserCreator`=20class=20allows=20for=20dynamic?= =?UTF-8?q?=20creation=20and=20loading=20of=20output=20parsers,=20while=20?= =?UTF-8?q?the=20`OutputParserFrontendNode`=20class=20provides=20a=20way?= =?UTF-8?q?=20to=20format=20the=20fields=20of=20an=20output=20parser.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../interface/output_parsers/__init__.py | 0 .../langflow/interface/output_parsers/base.py | 64 +++++++++++++++++++ .../template/frontend_node/output_parsers.py | 10 +++ 3 files changed, 74 insertions(+) create mode 100644 src/backend/langflow/interface/output_parsers/__init__.py create mode 100644 src/backend/langflow/interface/output_parsers/base.py create mode 100644 src/backend/langflow/template/frontend_node/output_parsers.py diff --git a/src/backend/langflow/interface/output_parsers/__init__.py b/src/backend/langflow/interface/output_parsers/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/langflow/interface/output_parsers/base.py b/src/backend/langflow/interface/output_parsers/base.py new file mode 100644 index 000000000..79cbdd98c --- /dev/null +++ b/src/backend/langflow/interface/output_parsers/base.py @@ -0,0 +1,64 @@ +from typing import Dict, List, Optional, Type + +from langchain import output_parsers + +from langflow.interface.base import LangChainTypeCreator +from langflow.interface.importing.utils import import_class +from langflow.settings import settings +from langflow.template.frontend_node.output_parsers import OutputParserFrontendNode +from langflow.utils.logger import logger +from langflow.utils.util import build_template_from_class, build_template_from_method + + +class OutputParserCreator(LangChainTypeCreator): + type_name: str = "output_parsers" + from_method_nodes = { + "StructuredOutputParser": "from_response_schemas", + } + + @property + def frontend_node_class(self) -> Type[OutputParserFrontendNode]: + return OutputParserFrontendNode + + @property + def type_to_loader_dict(self) -> Dict: + if self.type_dict is None: + self.type_dict = { + output_parser_name: import_class( + f"langchain.output_parsers.{output_parser_name}" + ) + # if output_parser_name is not lower case it is a class + for output_parser_name in output_parsers.__all__ + } + self.type_dict = { + name: output_parser + for name, output_parser in self.type_dict.items() + if name in settings.output_parsers or settings.dev + } + return self.type_dict + + def get_signature(self, name: str) -> Optional[Dict]: + try: + if name in self.from_method_nodes: + return build_template_from_method( + name, + type_to_cls_dict=self.type_to_loader_dict, + method_name=self.from_method_nodes[name], + ) + else: + return build_template_from_class( + name, + type_to_cls_dict=self.type_to_loader_dict, + ) + except ValueError as exc: + # raise ValueError("OutputParser not found") from exc + logger.error(f"OutputParser {name} not found: {exc}") + except AttributeError as exc: + logger.error(f"OutputParser {name} not loaded: {exc}") + return None + + def to_list(self) -> List[str]: + return list(self.type_to_loader_dict.keys()) + + +output_parser_creator = OutputParserCreator() diff --git a/src/backend/langflow/template/frontend_node/output_parsers.py b/src/backend/langflow/template/frontend_node/output_parsers.py new file mode 100644 index 000000000..e9b4d3706 --- /dev/null +++ b/src/backend/langflow/template/frontend_node/output_parsers.py @@ -0,0 +1,10 @@ +from typing import Optional +from langflow.template.field.base import TemplateField +from langflow.template.frontend_node.base import FrontendNode + + +class OutputParserFrontendNode(FrontendNode): + @staticmethod + def format_field(field: TemplateField, name: Optional[str] = None) -> None: + FrontendNode.format_field(field, name) + field.show = True