From 92b747b6da55a81e794d3603c43d155ef4855aca Mon Sep 17 00:00:00 2001 From: gustavoschaedler Date: Wed, 5 Jul 2023 00:46:51 +0100 Subject: [PATCH] Update Vertex params with code type and add a my_conversation method to the MyPythonClass. Modify the instantiate_tool function to properly handle the CustomComponent node type. Add a dynamic field to the FrontendNode class. --- src/backend/langflow/graph/vertex/base.py | 2 +- .../langflow/interface/importing/utils.py | 27 +++++++++---------- .../langflow/interface/initialize/loading.py | 5 ++-- .../langflow/template/frontend_node/base.py | 5 +++- src/backend/langflow/utils/constants.py | 20 +++++++------- src/backend/langflow/utils/validate.py | 12 +++++++++ 6 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/backend/langflow/graph/vertex/base.py b/src/backend/langflow/graph/vertex/base.py index a7fcf88b5..e3838714e 100644 --- a/src/backend/langflow/graph/vertex/base.py +++ b/src/backend/langflow/graph/vertex/base.py @@ -110,7 +110,7 @@ class Vertex: file_path = value.get("file_path") params[key] = file_path - elif value.get("type") in ["str", "prompt"] and params.get(key) is None: + elif value.get("type") in ["code", "str", "prompt"] and params.get(key) is None: params[key] = value.get("value") # Add _type to params self.params = params diff --git a/src/backend/langflow/interface/importing/utils.py b/src/backend/langflow/interface/importing/utils.py index 843b745fa..cf804e67d 100644 --- a/src/backend/langflow/interface/importing/utils.py +++ b/src/backend/langflow/interface/importing/utils.py @@ -169,25 +169,22 @@ def get_function_custom(code): class_name = "MyPythonClass" code = """ +from langchain.llms import OpenAI from langchain.chains import ConversationChain +from langchain.memory import ConversationBufferMemory + class MyPythonClass: - def __init__(self, title: str, author: str, year_published: int): - self.title = title - self.author = author - self.year_published = year_published + def my_conversation(self): + llm = OpenAI(temperature=0) + return ConversationChain( + llm=llm, verbose=True, memory=ConversationBufferMemory() + ) - def get_details(self): - return f"Title: {self.title}, Author: {self.author}, Year Published: {self.year_published}" - - def update_year_published(self, new_year: int): - self.year_published = new_year - print(f"The year of publication has been updated to {new_year}.") - - def build(self, name, my_int, my_str, my_bool, no_type): - # do something... - print("x") - return "" + def build(self, name: str) -> ConversationChain: + conversation = self.my_conversation() + + return conversation """ return validate.create_class(code, class_name) diff --git a/src/backend/langflow/interface/initialize/loading.py b/src/backend/langflow/interface/initialize/loading.py index 33e070d94..53679ea9a 100644 --- a/src/backend/langflow/interface/initialize/loading.py +++ b/src/backend/langflow/interface/initialize/loading.py @@ -178,9 +178,8 @@ def instantiate_tool(node_type, class_object, params): params["func"] = get_function(params.get("code")) return class_object(**params) elif node_type == "CustomComponent": - return get_function_custom(params.get("code")) - # params["func"] = get_function_custom(params.get("code")) - # return class_object(**params) + params["func"] = get_function_custom(params.get("code")) + return class_object(**params) # For backward compatibility elif node_type == "PythonFunction": function_string = params["code"] diff --git a/src/backend/langflow/template/frontend_node/base.py b/src/backend/langflow/template/frontend_node/base.py index 2663164e0..84ec33e00 100644 --- a/src/backend/langflow/template/frontend_node/base.py +++ b/src/backend/langflow/template/frontend_node/base.py @@ -16,6 +16,7 @@ class FrontendNode(BaseModel): name: str = "" display_name: str = "" custom_fields: List[str] = [] + dynamic: bool = False def to_dict(self) -> dict: return { @@ -25,6 +26,7 @@ class FrontendNode(BaseModel): "base_classes": self.base_classes, "display_name": self.display_name or self.name, "custom_fields": self.custom_fields, + "dynamic": self.dynamic, }, } @@ -186,7 +188,8 @@ class FrontendNode(BaseModel): def should_be_password(key: str, show: bool) -> bool: """Determines whether the field should be a password field.""" return ( - any(text in key.lower() for text in {"password", "token", "api", "key"}) + any(text in key.lower() + for text in {"password", "token", "api", "key"}) and show ) diff --git a/src/backend/langflow/utils/constants.py b/src/backend/langflow/utils/constants.py index b9449ecf2..8cec38c6e 100644 --- a/src/backend/langflow/utils/constants.py +++ b/src/backend/langflow/utils/constants.py @@ -50,20 +50,22 @@ def python_function(text: str) -> str: """ DEFAULT_CUSTOM_COMPONENT_CODE = """ +from langchain.llms import OpenAI from langchain.chains import ConversationChain +from langchain.memory import ConversationBufferMemory class MyPythonClass: - def __init__(self, name: str, year: int): - self.name = name - self.year = year + def my_conversation(self): + llm = OpenAI(temperature=0) + return ConversationChain( + llm=llm, verbose=True, memory=ConversationBufferMemory() + ) - def get_details(self): - return f"Name: {self.name}, Year: {self.year}" - - def build(self, name: str, year: int, true_or_false: bool, no_type) -> ConversationChain: - # do something... - return ConversationChain() + def build(self, name: str) -> ConversationChain: + conversation = self.my_conversation() + + return conversation """ DIRECT_TYPES = ["str", "bool", "code", "int", "float", "Any", "prompt"] diff --git a/src/backend/langflow/utils/validate.py b/src/backend/langflow/utils/validate.py index 35a831d15..3dcac8a66 100644 --- a/src/backend/langflow/utils/validate.py +++ b/src/backend/langflow/utils/validate.py @@ -186,6 +186,16 @@ def create_class(code, class_name): raise ModuleNotFoundError( f"Module {alias.name} not found. Please install it and try again." ) from e + elif isinstance(node, ast.ImportFrom): + try: + imported_module = importlib.import_module(node.module) + for alias in node.names: + exec_globals[alias.name] = getattr( + imported_module, alias.name) + except ModuleNotFoundError as e: + raise ModuleNotFoundError( + f"Module {node.module} not found. Please install it and try again." + ) from e class_code = next( node @@ -209,6 +219,8 @@ def create_class(code, class_name): instance = exec_globals[class_name](*args, **kwargs) return instance + build.__globals__.update(exec_globals) + return build