feat: implemented file loading and toolkit

This commit is contained in:
Gabriel Almeida 2023-03-31 14:03:32 -03:00
commit fbca59d42c
2 changed files with 64 additions and 18 deletions

View file

@ -3,19 +3,22 @@
# - Defer prompts building to the last moment or when they have all the tools # - Defer prompts building to the last moment or when they have all the tools
# - Build each inner agent first, then build the outer agent # - Build each inner agent first, then build the outer agent
from copy import deepcopy
import types import types
from copy import deepcopy
from typing import Any, Dict, List from typing import Any, Dict, List
from langflow.interface.listing import ALL_TYPES_DICT
from langflow.graph.utils import load_dict
from langflow.interface import loading from langflow.interface import loading
from langflow.interface.listing import ALL_TYPES_DICT
from langflow.interface.tools.base import tool_creator from langflow.interface.tools.base import tool_creator
class Node: class Node:
def __init__(self, data: Dict): def __init__(self, data: Dict, base_type: str | None = None) -> None:
self.id: str = data["id"] self.id: str = data["id"]
self._data = data self._data = data
self.edges: List[Edge] = [] self.edges: List[Edge] = []
self.base_type: str | None = base_type
self._parse_data() self._parse_data()
self._built_object = None self._built_object = None
self._built = False self._built = False
@ -44,6 +47,11 @@ class Node:
self.node_type = ( self.node_type = (
self.data["type"] if "Tool" not in self.output else template_dict["_type"] self.data["type"] if "Tool" not in self.output else template_dict["_type"]
) )
if self.base_type is None:
for base_type, value in ALL_TYPES_DICT.items():
if self.node_type in value:
self.base_type = base_type
break
def _build_params(self): def _build_params(self):
# Some params are required, some are optional # Some params are required, some are optional
@ -71,7 +79,18 @@ class Node:
continue continue
# If the type is not transformable to a python base class # If the type is not transformable to a python base class
# then we need to get the edge that connects to this node # then we need to get the edge that connects to this node
if value["type"] not in ["str", "bool", "code"]: if value["type"] == "file":
# Load the type in value.get('suffixes') using
# what is inside value.get('content')
# value.get('value') is the file name
type_to_load = value.get("suffixes")
file_name = value.get("value")
content = value.get("content")
# Now
loaded_dict = load_dict(file_name, content, type_to_load)
params[key] = loaded_dict
elif value["type"] not in ["str", "bool", "code", "int", "float"]:
# Get the edge that connects to this node # Get the edge that connects to this node
edge = next( edge = next(
( (
@ -138,17 +157,15 @@ class Node:
# Get the class from LANGCHAIN_TYPES_DICT # Get the class from LANGCHAIN_TYPES_DICT
# and instantiate it with the params # and instantiate it with the params
# and return the instance # and return the instance
for base_type, value in ALL_TYPES_DICT.items():
if base_type == "tools":
value = tool_creator.type_to_loader_dict
if self.node_type in value: try:
self._built_object = loading.instantiate_class( self._built_object = loading.instantiate_class(
node_type=self.node_type, node_type=self.node_type,
base_type=base_type, base_type=self.base_type,
params=self.params, params=self.params,
) )
break except Exception as exc:
raise ValueError(f"Error building node {self.node_type}") from exc
if self._built_object is None: if self._built_object is None:
raise ValueError(f"Node type {self.node_type} not found") raise ValueError(f"Node type {self.node_type} not found")

View file

@ -1,12 +1,28 @@
from langflow.interface.base import LangChainTypeCreator from typing import Callable, Dict, List
from langflow.utils.util import build_template_from_class
from typing import Dict, List
from langchain.agents import agent_toolkits from langchain.agents import agent_toolkits
from langflow.interface.importing.utils import import_class
from langflow.interface.base import LangChainTypeCreator
from langflow.interface.importing.utils import import_class, import_module
from langflow.utils.util import build_template_from_class
class ToolkitCreator(LangChainTypeCreator): class ToolkitCreator(LangChainTypeCreator):
type_name: str = "toolkits" type_name: str = "toolkits"
all_types: List[str] = agent_toolkits.__all__
create_functions: Dict = {
"JsonToolkit": [],
"SQLDatabaseToolkit": [],
"OpenAPIToolkit": ["create_openapi_agent"],
"VectorStoreToolkit": [
"create_vectorstore_agent",
"create_vectorstore_router_agent",
"VectorStoreInfo",
],
"ZapierToolkit": [],
"PandasToolkit": ["create_pandas_dataframe_agent"],
"CSVToolkit": ["create_csv_agent"],
}
@property @property
def type_to_loader_dict(self) -> Dict: def type_to_loader_dict(self) -> Dict:
@ -19,6 +35,7 @@ class ToolkitCreator(LangChainTypeCreator):
for toolkit_name in agent_toolkits.__all__ for toolkit_name in agent_toolkits.__all__
if not toolkit_name.islower() if not toolkit_name.islower()
} }
return self.type_dict return self.type_dict
def get_signature(self, name: str) -> Dict | None: def get_signature(self, name: str) -> Dict | None:
@ -30,5 +47,17 @@ class ToolkitCreator(LangChainTypeCreator):
def to_list(self) -> List[str]: def to_list(self) -> List[str]:
return list(self.type_to_loader_dict.keys()) return list(self.type_to_loader_dict.keys())
def get_create_function(self, name: str) -> Callable | None:
if loader_name := self.create_functions.get(name, None):
# import loader
return import_module(
f"from langchain.agents.agent_toolkits import {loader_name[0]}"
)
return None
def has_create_function(self, name: str) -> bool:
# check if the function list is not empty
return bool(self.create_functions.get(name, None))
toolkits_creator = ToolkitCreator() toolkits_creator = ToolkitCreator()