From 10d88aecc83b33a62c0c8ea6d3da9630eebfcd3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Boschi?= Date: Mon, 8 Jul 2024 16:12:47 +0200 Subject: [PATCH 1/5] feat: migrate agents and toolkits to Component syntax --- .../base/langflow/base/agents/agent.py | 148 ++++++++++-------- .../base/langflow/base/vectorstores/model.py | 13 +- .../langflow/components/agents/CSVAgent.py | 55 ++++--- .../langflow/components/agents/JsonAgent.py | 49 ++++-- .../components/agents/OpenAIToolsAgent.py | 39 +++++ .../components/agents/OpenAPIAgent.py | 62 ++++++++ .../langflow/components/agents/SQLAgent.py | 47 +++--- .../components/agents/ToolCallingAgent.py | 100 ++---------- .../components/agents/VectorStoreAgent.py | 36 +++-- .../agents/VectorStoreRouterAgent.py | 37 +++-- .../langflow/components/agents/XMLAgent.py | 143 +++++------------ .../components/prototypes/RunnableExecutor.py | 83 +++++----- .../components/toolkits/JsonToolkit.py | 30 ---- .../components/toolkits/OpenAPIToolkit.py | 35 ----- .../components/toolkits/VectorStoreInfo.py | 53 +++++-- .../toolkits/VectorStoreRouterToolkit.py | 23 --- .../components/toolkits/VectorStoreToolkit.py | 25 --- 17 files changed, 469 insertions(+), 509 deletions(-) create mode 100644 src/backend/base/langflow/components/agents/OpenAIToolsAgent.py create mode 100644 src/backend/base/langflow/components/agents/OpenAPIAgent.py delete mode 100644 src/backend/base/langflow/components/toolkits/JsonToolkit.py delete mode 100644 src/backend/base/langflow/components/toolkits/OpenAPIToolkit.py delete mode 100644 src/backend/base/langflow/components/toolkits/VectorStoreRouterToolkit.py delete mode 100644 src/backend/base/langflow/components/toolkits/VectorStoreToolkit.py diff --git a/src/backend/base/langflow/base/agents/agent.py b/src/backend/base/langflow/base/agents/agent.py index b24cf1984b3..e694b2a435c 100644 --- a/src/backend/base/langflow/base/agents/agent.py +++ b/src/backend/base/langflow/base/agents/agent.py @@ -1,78 +1,100 @@ -from typing import List, Optional, Union, cast +from abc import abstractmethod +from langchain.agents.agent import RunnableAgent from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent from langchain_core.messages import BaseMessage from langchain_core.runnables import Runnable from langflow.base.agents.utils import data_to_messages, get_agents_list -from langflow.custom import CustomComponent +from langflow.custom import CustomComponent, Component from langflow.field_typing import Text, Tool +from langflow.inputs import BoolInput, IntInput, HandleInput from langflow.schema import Data +from langflow.template import Output -class LCAgentComponent(CustomComponent): - def get_agents_list(self): - return get_agents_list() +class LCAgentComponent(Component): + trace_type = "agent" + _base_inputs = [ + BoolInput( + name="handle_parsing_errors", + display_name="Handle Parse Errors", + value=True, + advanced=True, + ), + BoolInput( + name="verbose", + display_name="Verbose", + value=True, + advanced=True, + ), + IntInput( + name="max_iterations", + display_name="Max Iterations", + value=15, + advanced=True, + ), + ] - def build_config(self): + outputs = [ + Output(display_name="Agent", name="agent", method="build_agent"), + ] + + def _validate_outputs(self): + required_output_methods = ["build_agent"] + output_names = [output.name for output in self.outputs] + for method_name in required_output_methods: + if method_name not in output_names: + raise ValueError(f"Output with name '{method_name}' must be defined.") + elif not hasattr(self, method_name): + raise ValueError(f"Method '{method_name}' must be defined.") + + def get_agent_kwargs(self, flatten: bool = False) -> dict: + base = { + "handle_parsing_errors": self.handle_parsing_errors, + "verbose": self.verbose, + "allow_dangerous_code": True, + } + agent_kwargs = { + "handle_parsing_errors": self.handle_parsing_errors, + "max_iterations": self.max_iterations, + } + if flatten: + return { + **base, + **agent_kwargs, + } return { - "lc": { - "display_name": "LangChain", - "info": "The LangChain to interact with.", - }, - "handle_parsing_errors": { - "display_name": "Handle Parsing Errors", - "info": "If True, the agent will handle parsing errors. If False, the agent will raise an error.", - "advanced": True, - }, - "output_key": { - "display_name": "Output Key", - "info": "The key to use to get the output from the agent.", - "advanced": True, - }, - "memory": { - "display_name": "Memory", - "info": "Memory to use for the agent.", - }, - "tools": { - "display_name": "Tools", - "info": "Tools the agent can use.", - }, - "input_value": { - "display_name": "Input", - "info": "Input text to pass to the agent.", - }, + **base, + "agent_executor_kwargs": agent_kwargs } - async def run_agent( - self, - agent: Union[Runnable, BaseSingleActionAgent, BaseMultiActionAgent, AgentExecutor], - inputs: str, - tools: List[Tool], - message_history: Optional[List[Data]] = None, - handle_parsing_errors: bool = True, - output_key: str = "output", - ) -> Text: - if isinstance(agent, AgentExecutor): - runnable = agent - else: - runnable = AgentExecutor.from_agent_and_tools( - agent=agent, # type: ignore - tools=tools, - verbose=True, - handle_parsing_errors=handle_parsing_errors, - ) - input_dict: dict[str, str | list[BaseMessage]] = {"input": inputs} - if message_history: - input_dict["chat_history"] = data_to_messages(message_history) - result = await runnable.ainvoke(input_dict) - self.status = result - if output_key in result: - return cast(str, result.get(output_key)) - elif "output" not in result: - if output_key != "output": - raise ValueError(f"Output key not found in result. Tried '{output_key}' and 'output'.") - else: - raise ValueError("Output key not found in result. Tried 'output'.") - return cast(str, result.get("output")) +class LCToolsAgentComponent(LCAgentComponent): + _base_inputs = LCAgentComponent._base_inputs + [ + HandleInput( + name="tools", + display_name="Tools", + input_types=["Tool"], + is_list=True, + ), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True + ), + ] + + def build_agent(self) -> AgentExecutor: + agent = self.creat_agent_runnable() + return AgentExecutor.from_agent_and_tools( + agent=RunnableAgent(runnable=agent, input_keys_arg=["input"], output_keys_arg=["output"]), + tools=self.tools, + **self.get_agent_kwargs(flatten=True) + ) + + @abstractmethod + def creat_agent_runnable(self) -> Runnable: + """Create the agent.""" + pass diff --git a/src/backend/base/langflow/base/vectorstores/model.py b/src/backend/base/langflow/base/vectorstores/model.py index a00b56e99c4..a8006409606 100644 --- a/src/backend/base/langflow/base/vectorstores/model.py +++ b/src/backend/base/langflow/base/vectorstores/model.py @@ -1,4 +1,4 @@ -from typing import List +from typing import List, cast from langchain_core.documents import Document from loguru import logger @@ -8,6 +8,7 @@ from langflow.helpers.data import docs_to_data from langflow.io import Output from langflow.schema import Data +from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo class LCVectorStoreComponent(Component): @@ -23,11 +24,16 @@ class LCVectorStoreComponent(Component): name="search_results", method="search_documents", ), + Output( + display_name="Vector Store", + name="vector_store", + method="cast_vector_store", + ) ] def _validate_outputs(self): # At least these three outputs must be defined - required_output_methods = ["build_base_retriever", "search_documents"] + required_output_methods = ["build_base_retriever", "search_documents", "build_vector_store"] output_names = [output.name for output in self.outputs] for method_name in required_output_methods: if method_name not in output_names: @@ -67,6 +73,9 @@ def search_with_vector_store( self.status = data return data + def cast_vector_store(self) -> VectorStore: + return cast(VectorStore, self.build_vector_store()) + def build_vector_store(self) -> VectorStore: """ Builds the Vector Store object.c diff --git a/src/backend/base/langflow/components/agents/CSVAgent.py b/src/backend/base/langflow/components/agents/CSVAgent.py index b336045703a..ad2352b7258 100644 --- a/src/backend/base/langflow/components/agents/CSVAgent.py +++ b/src/backend/base/langflow/components/agents/CSVAgent.py @@ -1,35 +1,44 @@ from langchain_experimental.agents.agent_toolkits.csv.base import create_csv_agent -from langflow.custom import CustomComponent -from langflow.field_typing import AgentExecutor, LanguageModel +from langflow.base.agents.agent import LCAgentComponent +from langflow.field_typing import AgentExecutor +from langflow.inputs import HandleInput, FileInput, DropdownInput +from langflow.template import Output -class CSVAgentComponent(CustomComponent): +class CSVAgentComponent(LCAgentComponent): display_name = "CSVAgent" description = "Construct a CSV agent from a CSV and tools." documentation = "https://python.langchain.com/docs/modules/agents/toolkits/csv" name = "CSVAgent" - def build_config(self): - return { - "llm": {"display_name": "LLM", "type": LanguageModel}, - "path": {"display_name": "Path", "field_type": "file", "suffixes": [".csv"], "file_types": [".csv"]}, - "handle_parsing_errors": {"display_name": "Handle Parse Errors", "advanced": True}, - "agent_type": { - "display_name": "Agent Type", - "options": ["zero-shot-react-description", "openai-functions", "openai-tools"], - "advanced": True, - }, - } + inputs = LCAgentComponent._base_inputs + [ + FileInput( + name="path", + display_name="File Path", + file_types=["csv"], + required=True + ), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True + ), + DropdownInput( + name="agent_type", + display_name="Agent Type", + advanced=True, + options=["zero-shot-react-description", "openai-functions", "openai-tools"], + value="openai-tools", + ), - def build( - self, llm: LanguageModel, path: str, handle_parsing_errors: bool = True, agent_type: str = "openai-tools" - ) -> AgentExecutor: - # Instantiate and return the CSV agent class with the provided llm and path + ] + + def build_agent(self) -> AgentExecutor: return create_csv_agent( - llm=llm, - path=path, - agent_type=agent_type, - verbose=True, - agent_executor_kwargs=dict(handle_parsing_errors=handle_parsing_errors), + llm=self.llm, + path=self.path, + agent_type=self.agent_type, + **self.get_agent_kwargs() ) diff --git a/src/backend/base/langflow/components/agents/JsonAgent.py b/src/backend/base/langflow/components/agents/JsonAgent.py index 3746e989d51..f3832ea8bbb 100644 --- a/src/backend/base/langflow/components/agents/JsonAgent.py +++ b/src/backend/base/langflow/components/agents/JsonAgent.py @@ -1,25 +1,46 @@ +from pathlib import Path + +import yaml from langchain.agents import AgentExecutor from langchain_community.agent_toolkits import create_json_agent from langchain_community.agent_toolkits.json.toolkit import JsonToolkit +from langchain_community.tools.json.tool import JsonSpec -from langflow.custom import CustomComponent -from langflow.field_typing import LanguageModel +from langflow.base.agents.agent import LCAgentComponent +from langflow.custom import Component +from langflow.inputs import BoolInput, HandleInput, FileInput +from langflow.template import Output -class JsonAgentComponent(CustomComponent): +class JsonAgentComponent(LCAgentComponent): display_name = "JsonAgent" description = "Construct a json agent from an LLM and tools." name = "JsonAgent" - def build_config(self): - return { - "llm": {"display_name": "LLM"}, - "toolkit": {"display_name": "Toolkit"}, - } + inputs = LCAgentComponent._base_inputs + [ + FileInput( + name="path", + display_name="File Path", + file_types=["json", "yaml", "yml"], + required=True + ), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True + ) + ] + def build_agent(self) -> AgentExecutor: + if self.path.endswith("yaml") or self.path.endswith("yml"): + yaml_dict = yaml.load(open(self.path, "r"), Loader=yaml.FullLoader) + spec = JsonSpec(dict_=yaml_dict) + else: + spec = JsonSpec.from_file(Path(self.path)) + toolkit = JsonToolkit(spec=spec) - def build( - self, - llm: LanguageModel, - toolkit: JsonToolkit, - ) -> AgentExecutor: - return create_json_agent(llm=llm, toolkit=toolkit) + return create_json_agent( + llm=self.llm, + toolkit=toolkit, + **self.get_agent_kwargs() + ) \ No newline at end of file diff --git a/src/backend/base/langflow/components/agents/OpenAIToolsAgent.py b/src/backend/base/langflow/components/agents/OpenAIToolsAgent.py new file mode 100644 index 00000000000..65f8d113ee1 --- /dev/null +++ b/src/backend/base/langflow/components/agents/OpenAIToolsAgent.py @@ -0,0 +1,39 @@ +from langchain.agents import create_openai_tools_agent +from langchain_core.prompts import ChatPromptTemplate, PromptTemplate, HumanMessagePromptTemplate + +from langflow.base.agents.agent import LCAgentComponent, LCToolsAgentComponent +from langflow.inputs import MultilineInput + + +class OpenAIToolsAgentComponent(LCToolsAgentComponent): + display_name: str = "OpenAI Tools Agent" + description: str = "Agent that uses tools via openai-tools." + icon = "LangChain" + beta = True + name = "OpenAIToolsAgent" + + inputs = LCToolsAgentComponent._base_inputs + [ + MultilineInput( + name="system_prompt", + display_name="System Prompt", + info="System prompt for the agent.", + value="You are a helpful assistant", + ), + MultilineInput( + name="user_prompt", + display_name="Prompt", + info="This prompt must contain 'input' key.", + value="{input}" + ), + ] + + def creat_agent_runnable(self): + if "input" not in self.user_prompt: + raise ValueError("Prompt must contain 'input' key.") + messages = [ + ("system", self.system_prompt), + HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template=self.user_prompt)), + ("placeholder", "{agent_scratchpad}") + ] + prompt = ChatPromptTemplate.from_messages(messages) + return create_openai_tools_agent(self.llm, self.tools, prompt) \ No newline at end of file diff --git a/src/backend/base/langflow/components/agents/OpenAPIAgent.py b/src/backend/base/langflow/components/agents/OpenAPIAgent.py new file mode 100644 index 00000000000..2762dc84792 --- /dev/null +++ b/src/backend/base/langflow/components/agents/OpenAPIAgent.py @@ -0,0 +1,62 @@ +from pathlib import Path + +import yaml +from langchain.agents import AgentExecutor +from langchain_community.agent_toolkits import create_openapi_agent +from langchain_community.agent_toolkits.json.toolkit import JsonToolkit +from langchain_community.tools.json.tool import JsonSpec +from langchain_community.agent_toolkits.openapi.toolkit import BaseToolkit, OpenAPIToolkit + +from langflow.base.agents.agent import LCAgentComponent +from langflow.custom import Component +from langflow.inputs import BoolInput, HandleInput, FileInput +from langchain_community.utilities.requests import TextRequestsWrapper + + +class OpenAPIAgentComponent(LCAgentComponent): + display_name = "OpenAPI Agent" + description = "Agent to interact with OpenAPI API." + name = "OpenAPIAgent" + + inputs = LCAgentComponent._base_inputs + [ + FileInput( + name="path", + display_name="File Path", + file_types=["json", "yaml", "yml"], + required=True + ), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True + ), + BoolInput( + name="allow_dangerous_requests", + display_name="Allow Dangerous Requests", + value=False, + required=True + ) + ] + def build_agent(self) -> AgentExecutor: + if self.path.endswith("yaml") or self.path.endswith("yml"): + yaml_dict = yaml.load(open(self.path, "r"), Loader=yaml.FullLoader) + spec = JsonSpec(dict_=yaml_dict) + else: + spec = JsonSpec.from_file(Path(self.path)) + requests_wrapper = TextRequestsWrapper() + toolkit = OpenAPIToolkit.from_llm( + llm=self.llm, + json_spec=spec, + requests_wrapper=requests_wrapper, + allow_dangerous_requests=self.allow_dangerous_requests, + ) + + agent_args = self.get_agent_kwargs() + agent_args["max_iterations"] = agent_args["agent_executor_kwargs"]["max_iterations"] + del agent_args["agent_executor_kwargs"]["max_iterations"] + return create_openapi_agent( + llm=self.llm, + toolkit=toolkit, + **agent_args + ) \ No newline at end of file diff --git a/src/backend/base/langflow/components/agents/SQLAgent.py b/src/backend/base/langflow/components/agents/SQLAgent.py index ddc6f49c603..3afef302203 100644 --- a/src/backend/base/langflow/components/agents/SQLAgent.py +++ b/src/backend/base/langflow/components/agents/SQLAgent.py @@ -1,32 +1,39 @@ -from typing import Callable, Union - from langchain.agents import AgentExecutor from langchain_community.agent_toolkits import SQLDatabaseToolkit from langchain_community.agent_toolkits.sql.base import create_sql_agent from langchain_community.utilities import SQLDatabase -from langflow.custom import CustomComponent -from langflow.field_typing import LanguageModel +from langflow.base.agents.agent import LCAgentComponent +from langflow.inputs import MessageTextInput, HandleInput -class SQLAgentComponent(CustomComponent): +class SQLAgentComponent(LCAgentComponent): display_name = "SQLAgent" description = "Construct an SQL agent from an LLM and tools." name = "SQLAgent" - def build_config(self): - return { - "llm": {"display_name": "LLM"}, - "database_uri": {"display_name": "Database URI"}, - "verbose": {"display_name": "Verbose", "value": False, "advanced": True}, - } + inputs = LCAgentComponent._base_inputs + [ + MessageTextInput( + name="database_uri", + display_name="Database URI", + required=True + ), + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True + ) + ] - def build( - self, - llm: LanguageModel, - database_uri: str, - verbose: bool = False, - ) -> Union[AgentExecutor, Callable]: - db = SQLDatabase.from_uri(database_uri) - toolkit = SQLDatabaseToolkit(db=db, llm=llm) - return create_sql_agent(llm=llm, toolkit=toolkit) + def build_agent(self) -> AgentExecutor: + db = SQLDatabase.from_uri(self.database_uri) + toolkit = SQLDatabaseToolkit(db=db, llm=self.llm) + agent_args = self.get_agent_kwargs() + agent_args["max_iterations"] = agent_args["agent_executor_kwargs"]["max_iterations"] + del agent_args["agent_executor_kwargs"]["max_iterations"] + return create_sql_agent( + llm=self.llm, + toolkit=toolkit, + **agent_args + ) \ No newline at end of file diff --git a/src/backend/base/langflow/components/agents/ToolCallingAgent.py b/src/backend/base/langflow/components/agents/ToolCallingAgent.py index c08c97ca55c..6294b85a25a 100644 --- a/src/backend/base/langflow/components/agents/ToolCallingAgent.py +++ b/src/backend/base/langflow/components/agents/ToolCallingAgent.py @@ -1,111 +1,39 @@ -from typing import Dict, List, cast +from langchain.agents import create_tool_calling_agent +from langchain_core.prompts import ChatPromptTemplate, PromptTemplate, HumanMessagePromptTemplate +from langflow.base.agents.agent import LCAgentComponent, LCToolsAgentComponent +from langflow.inputs import MultilineInput -from langchain.agents import AgentExecutor, BaseSingleActionAgent -from langchain.agents.tool_calling_agent.base import create_tool_calling_agent -from langchain_core.prompts import ChatPromptTemplate -from langflow.custom import Component -from langflow.io import BoolInput, HandleInput, MessageTextInput, Output -from langflow.schema import Data -from langflow.schema.message import Message - - -class ToolCallingAgentComponent(Component): +class ToolCallingAgentComponent(LCToolsAgentComponent): display_name: str = "Tool Calling Agent" - description: str = "Agent that uses tools. Only models that are compatible with function calling are supported." + description: str = "Agent that uses tools" icon = "LangChain" beta = True name = "ToolCallingAgent" - inputs = [ - MessageTextInput( + inputs = LCToolsAgentComponent._base_inputs + [ + MultilineInput( name="system_prompt", display_name="System Prompt", info="System prompt for the agent.", value="You are a helpful assistant", ), - MessageTextInput( - name="input_value", - display_name="Inputs", - info="Input text to pass to the agent.", - ), - MessageTextInput( + MultilineInput( name="user_prompt", display_name="Prompt", info="This prompt must contain 'input' key.", - value="{input}", - advanced=True, - ), - BoolInput( - name="handle_parsing_errors", - display_name="Handle Parsing Errors", - info="If True, the agent will handle parsing errors. If False, the agent will raise an error.", - advanced=True, - value=True, - ), - HandleInput( - name="memory", - display_name="Memory", - input_types=["Data"], - info="Memory to use for the agent.", - ), - HandleInput( - name="tools", - display_name="Tools", - input_types=["Tool"], - is_list=True, - ), - HandleInput( - name="llm", - display_name="LLM", - input_types=["LanguageModel"], + value="{input}" ), ] - outputs = [ - Output(display_name="Text", name="text_output", method="run_agent"), - ] - async def run_agent(self) -> Message: + def creat_agent_runnable(self): if "input" not in self.user_prompt: raise ValueError("Prompt must contain 'input' key.") messages = [ ("system", self.system_prompt), - ( - "placeholder", - "{chat_history}", - ), - ("human", self.user_prompt), - ("placeholder", "{agent_scratchpad}"), + HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template=self.user_prompt)), + ("placeholder", "{agent_scratchpad}") ] prompt = ChatPromptTemplate.from_messages(messages) - agent = create_tool_calling_agent(self.llm, self.tools, prompt) - - runnable = AgentExecutor.from_agent_and_tools( - agent=cast(BaseSingleActionAgent, agent), - tools=self.tools, - verbose=True, - handle_parsing_errors=self.handle_parsing_errors, - ) - input_dict: dict[str, str | list[Dict[str, str]]] = {"input": self.input_value} - if hasattr(self, "memory") and self.memory: - input_dict["chat_history"] = self.convert_chat_history(self.memory) - result = await runnable.ainvoke(input_dict) - - if "output" not in result: - raise ValueError("Output key not found in result. Tried 'output'.") - - results = result["output"] - if isinstance(results, list): - result_string = "\n".join([r["text"] for r in results if "text" in r and r.get("type") == "text"]) - else: - result_string = results - self.status = result_string - return Message(text=result_string) - - def convert_chat_history(self, chat_history: List[Data]) -> List[Dict[str, str]]: - messages = [] - for item in chat_history: - role = "user" if item.sender == "User" else "assistant" - messages.append({"role": role, "content": item.text}) - return messages + return create_tool_calling_agent(self.llm, self.tools, prompt) \ No newline at end of file diff --git a/src/backend/base/langflow/components/agents/VectorStoreAgent.py b/src/backend/base/langflow/components/agents/VectorStoreAgent.py index 1d3a5e890f9..9cd52a84843 100644 --- a/src/backend/base/langflow/components/agents/VectorStoreAgent.py +++ b/src/backend/base/langflow/components/agents/VectorStoreAgent.py @@ -2,25 +2,31 @@ from langchain.agents import AgentExecutor, create_vectorstore_agent from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreToolkit +from langflow.base.agents.agent import LCAgentComponent +from langflow.inputs import HandleInput -from langflow.custom import CustomComponent -from langflow.field_typing import LanguageModel - -class VectorStoreAgentComponent(CustomComponent): +class VectorStoreAgentComponent(LCAgentComponent): display_name = "VectorStoreAgent" description = "Construct an agent from a Vector Store." name = "VectorStoreAgent" - def build_config(self): - return { - "llm": {"display_name": "LLM"}, - "vector_store_toolkit": {"display_name": "Vector Store Info"}, - } + inputs = LCAgentComponent._base_inputs + [ + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True + ), + HandleInput( + name="vectorstore", + display_name="Vector Store", + input_types=["VectorStoreInfo"], + required=True + ) + ] - def build( - self, - llm: LanguageModel, - vector_store_toolkit: VectorStoreToolkit, - ) -> Union[AgentExecutor, Callable]: - return create_vectorstore_agent(llm=llm, toolkit=vector_store_toolkit) + def build_agent(self) -> AgentExecutor: + toolkit = VectorStoreToolkit(vectorstore_info=self.vectorstore, llm=self.llm) + return create_vectorstore_agent(llm=self.llm, toolkit=toolkit, + **self.get_agent_kwargs()) \ No newline at end of file diff --git a/src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py b/src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py index 7750b2e01ac..aa6f397ee9a 100644 --- a/src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py +++ b/src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py @@ -1,22 +1,33 @@ -from typing import Callable - from langchain.agents import create_vectorstore_router_agent -from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit -from langflow.field_typing import LanguageModel +from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit, VectorStoreInfo -from langflow.custom import CustomComponent +from langflow.base.agents.agent import LCAgentComponent +from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent +from langflow.inputs import HandleInput -class VectorStoreRouterAgentComponent(CustomComponent): +class VectorStoreRouterAgentComponent(LCAgentComponent): display_name = "VectorStoreRouterAgent" description = "Construct an agent from a Vector Store Router." name = "VectorStoreRouterAgent" - def build_config(self): - return { - "llm": {"display_name": "LLM"}, - "vectorstoreroutertoolkit": {"display_name": "Vector Store Router Toolkit"}, - } + inputs = LCAgentComponent._base_inputs + [ + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True + ), + HandleInput( + name="vectorstores", + display_name="Vector Stores", + input_types=["VectorStoreInfo"], + is_list=True, + required=True + ) + ] - def build(self, llm: LanguageModel, vectorstoreroutertoolkit: VectorStoreRouterToolkit) -> Callable: - return create_vectorstore_router_agent(llm=llm, toolkit=vectorstoreroutertoolkit) + def build_agent(self) -> AgentExecutor: + toolkit = VectorStoreRouterToolkit(vectorstores=self.vectorstores, llm=self.llm) + return create_vectorstore_router_agent(llm=self.llm, toolkit=toolkit, + **self.get_agent_kwargs()) \ No newline at end of file diff --git a/src/backend/base/langflow/components/agents/XMLAgent.py b/src/backend/base/langflow/components/agents/XMLAgent.py index 7972f8dfb89..6d1804f5c90 100644 --- a/src/backend/base/langflow/components/agents/XMLAgent.py +++ b/src/backend/base/langflow/components/agents/XMLAgent.py @@ -1,111 +1,52 @@ -from typing import List, Optional - from langchain.agents import create_xml_agent -from langchain_core.prompts import ChatPromptTemplate +from langchain_core.prompts import ChatPromptTemplate, PromptTemplate, HumanMessagePromptTemplate -from langflow.base.agents.agent import LCAgentComponent -from langflow.field_typing import LanguageModel, Text, Tool -from langflow.schema import Data +from langflow.base.agents.agent import LCAgentComponent, LCToolsAgentComponent +from langflow.inputs import MultilineInput -class XMLAgentComponent(LCAgentComponent): - display_name = "XMLAgent" - description = "Construct an XML agent from an LLM and tools." +class XMLAgentComponent(LCToolsAgentComponent): + display_name: str = "XML Agent" + description: str = "Agent that uses tools formatting instructions as xml to the Language Model." + icon = "LangChain" + beta = True name = "XMLAgent" - def build_config(self): - return { - "llm": {"display_name": "LLM"}, - "tools": {"display_name": "Tools"}, - "user_prompt": { - "display_name": "Prompt", - "multiline": True, - "info": "This prompt must contain 'tools' and 'agent_scratchpad' keys.", - "value": """You are a helpful assistant. Help the user answer any questions. - - You have access to the following tools: - - {tools} - - In order to use a tool, you can use and tags. You will then get back a response in the form - For example, if you have a tool called 'search' that could run a google search, in order to search for the weather in SF you would respond: - - searchweather in SF - 64 degrees - - When you are done, respond with a final answer between . For example: - - The weather in SF is 64 degrees - - Begin! - - Previous Conversation: - {chat_history} - - Question: {input} - {agent_scratchpad}""", - }, - "system_message": { - "display_name": "System Message", - "info": "System message to be passed to the LLM.", - "advanced": True, - }, - "tool_template": { - "display_name": "Tool Template", - "info": "Template for rendering tools in the prompt. Tools have 'name' and 'description' keys.", - "advanced": True, - }, - "handle_parsing_errors": { - "display_name": "Handle Parsing Errors", - "info": "If True, the agent will handle parsing errors. If False, the agent will raise an error.", - "advanced": True, - }, - "message_history": { - "display_name": "Message History", - "info": "Message history to pass to the agent.", - }, - "input_value": { - "display_name": "Inputs", - "info": "Input text to pass to the agent.", - }, - } - - async def build( - self, - input_value: str, - llm: LanguageModel, - tools: List[Tool], - user_prompt: str = "{input}", - system_message: str = "You are a helpful assistant", - message_history: Optional[List[Data]] = None, - tool_template: str = "{name}: {description}", - handle_parsing_errors: bool = True, - ) -> Text: - if "input" not in user_prompt: - raise ValueError("Prompt must contain 'input' key.") - - def render_tool_description(tools): - return "\n".join( - [tool_template.format(name=tool.name, description=tool.description, args=tool.args) for tool in tools] - ) + inputs = LCToolsAgentComponent._base_inputs + [ + MultilineInput( + name="user_prompt", + display_name="Prompt", + value=""" +You are a helpful assistant. Help the user answer any questions. + +You have access to the following tools: + +{tools} + +In order to use a tool, you can use and tags. You will then get back a response in the form + +For example, if you have a tool called 'search' that could run a google search, in order to search for the weather in SF you would respond: + +searchweather in SF + +64 degrees + +When you are done, respond with a final answer between . For example: + +The weather in SF is 64 degrees + +Begin! + +Question: {input} + +{agent_scratchpad} + """ + ), + ] + def creat_agent_runnable(self): messages = [ - ("system", system_message), - ( - "placeholder", - "{chat_history}", - ), - ("human", user_prompt), - ("placeholder", "{agent_scratchpad}"), + HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template=self.user_prompt)) ] prompt = ChatPromptTemplate.from_messages(messages) - agent = create_xml_agent(llm, tools, prompt, tools_renderer=render_tool_description) - result = await self.run_agent( - agent=agent, - inputs=input_value, - tools=tools, - message_history=message_history, - handle_parsing_errors=handle_parsing_errors, - ) - self.status = result - return result + return create_xml_agent(self.llm, self.tools, prompt) \ No newline at end of file diff --git a/src/backend/base/langflow/components/prototypes/RunnableExecutor.py b/src/backend/base/langflow/components/prototypes/RunnableExecutor.py index ab85e1e9c86..2ddd130f961 100644 --- a/src/backend/base/langflow/components/prototypes/RunnableExecutor.py +++ b/src/backend/base/langflow/components/prototypes/RunnableExecutor.py @@ -1,43 +1,48 @@ -from langchain_core.runnables import Runnable +from langflow.custom import Component +from langflow.inputs import HandleInput, MessageTextInput +from langflow.schema.message import Message +from langflow.template import Output -from langflow.custom import CustomComponent -from langflow.field_typing import Text - -class RunnableExecComponent(CustomComponent): +class RunnableExecComponent(Component): description = "Execute a runnable. It will try to guess the input and output keys." display_name = "Runnable Executor" name = "RunnableExecutor" beta: bool = True - field_order = [ - "input_key", - "output_key", - "input_value", - "runnable", + + inputs = [ + MessageTextInput( + name="input_value", + display_name="Input", + required=True + ), + HandleInput( + name="runnable", + display_name="Agent Executor", + input_types=["Chain", "AgentExecutor", "Agent", "Runnable"], + required=True + ), + MessageTextInput( + name="input_key", + display_name="Input Key", + value="input", + advanced=True, + ), + MessageTextInput( + name="output_key", + display_name="Output Key", + value="output", + advanced=True, + ), ] - def build_config(self): - return { - "input_key": { - "display_name": "Input Key", - "info": "The key to use for the input.", - "advanced": True, - }, - "input_value": { - "display_name": "Inputs", - "info": "The inputs to pass to the runnable.", - }, - "runnable": { - "display_name": "Runnable", - "info": "The runnable to execute.", - "input_types": ["Chain", "AgentExecutor", "Agent", "Runnable"], - }, - "output_key": { - "display_name": "Output Key", - "info": "The key to use for the output.", - "advanced": True, - }, - } + outputs = [ + Output( + display_name="Text", + name="text", + method="build_executor", + ), + ] def get_output(self, result, input_key, output_key): """ @@ -107,16 +112,10 @@ def get_input_dict(self, runnable, input_key, input_value): status = f"Warning: The input key is not '{input_key}'. The input key is '{runnable.input_keys}'." return input_dict, status - def build( - self, - input_value: Text, - runnable: Runnable, - input_key: str = "input", - output_key: str = "output", - ) -> Text: - input_dict, status = self.get_input_dict(runnable, input_key, input_value) - result = runnable.invoke(input_dict) - result_value, _status = self.get_output(result, input_key, output_key) + def build_executor(self) -> Message: + input_dict, status = self.get_input_dict(self.runnable, self.input_key, self.input_value) + result = self.runnable.invoke(input_dict) + result_value, _status = self.get_output(result, self.input_key, self.output_key) status += _status status += f"\n\nOutput: {result_value}\n\nRaw Output: {result}" self.status = status diff --git a/src/backend/base/langflow/components/toolkits/JsonToolkit.py b/src/backend/base/langflow/components/toolkits/JsonToolkit.py deleted file mode 100644 index 96dc3324853..00000000000 --- a/src/backend/base/langflow/components/toolkits/JsonToolkit.py +++ /dev/null @@ -1,30 +0,0 @@ -from pathlib import Path - -import yaml -from langchain_community.agent_toolkits.json.toolkit import JsonToolkit -from langchain_community.tools.json.tool import JsonSpec - -from langflow.custom import CustomComponent - - -class JsonToolkitComponent(CustomComponent): - display_name = "JsonToolkit" - description = "Toolkit for interacting with a JSON spec." - name = "JsonToolkit" - - def build_config(self): - return { - "path": { - "display_name": "Path", - "field_type": "file", - "file_types": ["json", "yaml", "yml"], - }, - } - - def build(self, path: str) -> JsonToolkit: - if path.endswith("yaml") or path.endswith("yml"): - yaml_dict = yaml.load(open(path, "r"), Loader=yaml.FullLoader) - spec = JsonSpec(dict_=yaml_dict) - else: - spec = JsonSpec.from_file(Path(path)) - return JsonToolkit(spec=spec) diff --git a/src/backend/base/langflow/components/toolkits/OpenAPIToolkit.py b/src/backend/base/langflow/components/toolkits/OpenAPIToolkit.py deleted file mode 100644 index 5a72c7f2f3c..00000000000 --- a/src/backend/base/langflow/components/toolkits/OpenAPIToolkit.py +++ /dev/null @@ -1,35 +0,0 @@ -from pathlib import Path - -import yaml -from langchain_community.agent_toolkits.openapi.toolkit import BaseToolkit, OpenAPIToolkit -from langchain_community.tools.json.tool import JsonSpec -from langchain_community.utilities.requests import TextRequestsWrapper - -from langflow.custom import CustomComponent -from langflow.field_typing import LanguageModel - - -class OpenAPIToolkitComponent(CustomComponent): - display_name = "OpenAPIToolkit" - description = "Toolkit for interacting with an OpenAPI API." - name = "OpenAPIToolkit" - - def build_config(self): - return { - "json_agent": {"display_name": "JSON Agent"}, - "requests_wrapper": {"display_name": "Text Requests Wrapper"}, - } - - def build(self, llm: LanguageModel, path: str, allow_dangerous_requests: bool = False) -> BaseToolkit: - if path.endswith("yaml") or path.endswith("yml"): - yaml_dict = yaml.load(open(path, "r"), Loader=yaml.FullLoader) - spec = JsonSpec(dict_=yaml_dict) - else: - spec = JsonSpec.from_file(Path(path)) - requests_wrapper = TextRequestsWrapper() - return OpenAPIToolkit.from_llm( - llm=llm, - json_spec=spec, - requests_wrapper=requests_wrapper, - allow_dangerous_requests=allow_dangerous_requests, - ) diff --git a/src/backend/base/langflow/components/toolkits/VectorStoreInfo.py b/src/backend/base/langflow/components/toolkits/VectorStoreInfo.py index c1c47e45f02..796c4bb8ef6 100644 --- a/src/backend/base/langflow/components/toolkits/VectorStoreInfo.py +++ b/src/backend/base/langflow/components/toolkits/VectorStoreInfo.py @@ -1,25 +1,44 @@ from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo -from langchain_core.vectorstores import VectorStore +from langflow.custom import Component +from langflow.inputs import HandleInput, MultilineInput, MessageTextInput +from langflow.template import Output -from langflow.custom import CustomComponent - -class VectorStoreInfoComponent(CustomComponent): +class VectorStoreInfoComponent(Component): display_name = "VectorStoreInfo" description = "Information about a VectorStore" name = "VectorStoreInfo" - def build_config(self): - return { - "vectorstore": {"display_name": "VectorStore"}, - "description": {"display_name": "Description", "multiline": True}, - "name": {"display_name": "Name"}, - } + inputs = [ + MessageTextInput( + name="vectorstore_name", + display_name="Name", + info="Name of the VectorStore", + required=True, + ), + MultilineInput( + name="vectorstore_description", + display_name="Description", + info="Description of the VectorStore", + required=True, + ), + HandleInput( + name="input_vectorstore", + display_name="Vector Store", + input_types=["VectorStore"], + required=True, + ) + ] - def build( - self, - vectorstore: VectorStore, - description: str, - name: str, - ) -> VectorStoreInfo: - return VectorStoreInfo(vectorstore=vectorstore, description=description, name=name) + outputs = [ + Output(display_name="Vector Store Info", name="info", method="build_info"), + ] + + def build_info(self) -> VectorStoreInfo: + self.status = { + "name": self.vectorstore_name, + "description": self.vectorstore_description, + } + return VectorStoreInfo(vectorstore=self.input_vectorstore, + description=self.vectorstore_description, + name=self.vectorstore_name) diff --git a/src/backend/base/langflow/components/toolkits/VectorStoreRouterToolkit.py b/src/backend/base/langflow/components/toolkits/VectorStoreRouterToolkit.py deleted file mode 100644 index 0676312a2de..00000000000 --- a/src/backend/base/langflow/components/toolkits/VectorStoreRouterToolkit.py +++ /dev/null @@ -1,23 +0,0 @@ -from typing import List, Union - -from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo, VectorStoreRouterToolkit - -from langflow.custom import CustomComponent -from langflow.field_typing import LanguageModel, Tool - - -class VectorStoreRouterToolkitComponent(CustomComponent): - display_name = "VectorStoreRouterToolkit" - description = "Toolkit for routing between Vector Stores." - name = "VectorStoreRouterToolkit" - - def build_config(self): - return { - "vectorstores": {"display_name": "Vector Stores"}, - "llm": {"display_name": "LLM"}, - } - - def build(self, vectorstores: List[VectorStoreInfo], llm: LanguageModel) -> Union[Tool, VectorStoreRouterToolkit]: - print("vectorstores", vectorstores) - print("llm", llm) - return VectorStoreRouterToolkit(vectorstores=vectorstores, llm=llm) diff --git a/src/backend/base/langflow/components/toolkits/VectorStoreToolkit.py b/src/backend/base/langflow/components/toolkits/VectorStoreToolkit.py deleted file mode 100644 index 74fe5d33c26..00000000000 --- a/src/backend/base/langflow/components/toolkits/VectorStoreToolkit.py +++ /dev/null @@ -1,25 +0,0 @@ -from typing import Union - -from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo, VectorStoreToolkit - -from langflow.custom import CustomComponent -from langflow.field_typing import LanguageModel, Tool - - -class VectorStoreToolkitComponent(CustomComponent): - display_name = "VectorStoreToolkit" - description = "Toolkit for interacting with a Vector Store." - name = "VectorStoreToolkit" - - def build_config(self): - return { - "vectorstore_info": {"display_name": "Vector Store Info"}, - "llm": {"display_name": "LLM"}, - } - - def build( - self, - vectorstore_info: VectorStoreInfo, - llm: LanguageModel, - ) -> Union[Tool, VectorStoreToolkit]: - return VectorStoreToolkit(vectorstore_info=vectorstore_info, llm=llm) From bd46628936028b648a80f01a451ec1bc4a70a077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Boschi?= Date: Mon, 8 Jul 2024 17:20:23 +0200 Subject: [PATCH 2/5] fix mypy --- src/backend/base/langflow/base/agents/agent.py | 5 ++++- src/backend/base/langflow/components/agents/JsonAgent.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/backend/base/langflow/base/agents/agent.py b/src/backend/base/langflow/base/agents/agent.py index e694b2a435c..efb3d93aad4 100644 --- a/src/backend/base/langflow/base/agents/agent.py +++ b/src/backend/base/langflow/base/agents/agent.py @@ -1,4 +1,6 @@ from abc import abstractmethod +from typing import List + from langchain.agents.agent import RunnableAgent from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent @@ -9,13 +11,14 @@ from langflow.custom import CustomComponent, Component from langflow.field_typing import Text, Tool from langflow.inputs import BoolInput, IntInput, HandleInput +from langflow.inputs.inputs import InputTypes from langflow.schema import Data from langflow.template import Output class LCAgentComponent(Component): trace_type = "agent" - _base_inputs = [ + _base_inputs: List[InputTypes] = [ BoolInput( name="handle_parsing_errors", display_name="Handle Parse Errors", diff --git a/src/backend/base/langflow/components/agents/JsonAgent.py b/src/backend/base/langflow/components/agents/JsonAgent.py index f3832ea8bbb..43bb4bd3186 100644 --- a/src/backend/base/langflow/components/agents/JsonAgent.py +++ b/src/backend/base/langflow/components/agents/JsonAgent.py @@ -15,7 +15,7 @@ class JsonAgentComponent(LCAgentComponent): display_name = "JsonAgent" description = "Construct a json agent from an LLM and tools." - name = "JsonAgent" + name: str = "JsonAgent" inputs = LCAgentComponent._base_inputs + [ FileInput( From 4d0db0b8b77c7b3be5404b2452cb9d45a0887cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Boschi?= Date: Mon, 8 Jul 2024 17:20:38 +0200 Subject: [PATCH 3/5] fix mypy --- src/backend/base/langflow/components/agents/JsonAgent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/base/langflow/components/agents/JsonAgent.py b/src/backend/base/langflow/components/agents/JsonAgent.py index 43bb4bd3186..f3832ea8bbb 100644 --- a/src/backend/base/langflow/components/agents/JsonAgent.py +++ b/src/backend/base/langflow/components/agents/JsonAgent.py @@ -15,7 +15,7 @@ class JsonAgentComponent(LCAgentComponent): display_name = "JsonAgent" description = "Construct a json agent from an LLM and tools." - name: str = "JsonAgent" + name = "JsonAgent" inputs = LCAgentComponent._base_inputs + [ FileInput( From d31fa8da1872a395ebb201c4906c50d3ef48d417 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:22:57 +0000 Subject: [PATCH 4/5] [autofix.ci] apply automated fixes --- .../base/langflow/base/agents/agent.py | 22 +++---------- .../base/langflow/base/vectorstores/model.py | 3 +- .../langflow/components/agents/CSVAgent.py | 23 ++----------- .../langflow/components/agents/JsonAgent.py | 25 +++------------ .../components/agents/OpenAIToolsAgent.py | 13 +++----- .../components/agents/OpenAPIAgent.py | 32 ++++--------------- .../langflow/components/agents/SQLAgent.py | 19 ++--------- .../components/agents/ToolCallingAgent.py | 14 +++----- .../components/agents/VectorStoreAgent.py | 19 ++--------- .../agents/VectorStoreRouterAgent.py | 18 ++++------- .../langflow/components/agents/XMLAgent.py | 8 ++--- .../components/prototypes/RunnableExecutor.py | 8 ++--- .../components/toolkits/VectorStoreInfo.py | 8 ++--- 13 files changed, 52 insertions(+), 160 deletions(-) diff --git a/src/backend/base/langflow/base/agents/agent.py b/src/backend/base/langflow/base/agents/agent.py index efb3d93aad4..e6b353058ca 100644 --- a/src/backend/base/langflow/base/agents/agent.py +++ b/src/backend/base/langflow/base/agents/agent.py @@ -3,16 +3,12 @@ from langchain.agents.agent import RunnableAgent -from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent -from langchain_core.messages import BaseMessage +from langchain.agents import AgentExecutor from langchain_core.runnables import Runnable -from langflow.base.agents.utils import data_to_messages, get_agents_list -from langflow.custom import CustomComponent, Component -from langflow.field_typing import Text, Tool +from langflow.custom import Component from langflow.inputs import BoolInput, IntInput, HandleInput from langflow.inputs.inputs import InputTypes -from langflow.schema import Data from langflow.template import Output @@ -67,10 +63,7 @@ def get_agent_kwargs(self, flatten: bool = False) -> dict: **base, **agent_kwargs, } - return { - **base, - "agent_executor_kwargs": agent_kwargs - } + return {**base, "agent_executor_kwargs": agent_kwargs} class LCToolsAgentComponent(LCAgentComponent): @@ -81,12 +74,7 @@ class LCToolsAgentComponent(LCAgentComponent): input_types=["Tool"], is_list=True, ), - HandleInput( - name="llm", - display_name="Language Model", - input_types=["LanguageModel"], - required=True - ), + HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), ] def build_agent(self) -> AgentExecutor: @@ -94,7 +82,7 @@ def build_agent(self) -> AgentExecutor: return AgentExecutor.from_agent_and_tools( agent=RunnableAgent(runnable=agent, input_keys_arg=["input"], output_keys_arg=["output"]), tools=self.tools, - **self.get_agent_kwargs(flatten=True) + **self.get_agent_kwargs(flatten=True), ) @abstractmethod diff --git a/src/backend/base/langflow/base/vectorstores/model.py b/src/backend/base/langflow/base/vectorstores/model.py index a8006409606..b989c0ecf6b 100644 --- a/src/backend/base/langflow/base/vectorstores/model.py +++ b/src/backend/base/langflow/base/vectorstores/model.py @@ -8,7 +8,6 @@ from langflow.helpers.data import docs_to_data from langflow.io import Output from langflow.schema import Data -from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreInfo class LCVectorStoreComponent(Component): @@ -28,7 +27,7 @@ class LCVectorStoreComponent(Component): display_name="Vector Store", name="vector_store", method="cast_vector_store", - ) + ), ] def _validate_outputs(self): diff --git a/src/backend/base/langflow/components/agents/CSVAgent.py b/src/backend/base/langflow/components/agents/CSVAgent.py index ad2352b7258..c8868552116 100644 --- a/src/backend/base/langflow/components/agents/CSVAgent.py +++ b/src/backend/base/langflow/components/agents/CSVAgent.py @@ -3,7 +3,6 @@ from langflow.base.agents.agent import LCAgentComponent from langflow.field_typing import AgentExecutor from langflow.inputs import HandleInput, FileInput, DropdownInput -from langflow.template import Output class CSVAgentComponent(LCAgentComponent): @@ -13,18 +12,8 @@ class CSVAgentComponent(LCAgentComponent): name = "CSVAgent" inputs = LCAgentComponent._base_inputs + [ - FileInput( - name="path", - display_name="File Path", - file_types=["csv"], - required=True - ), - HandleInput( - name="llm", - display_name="Language Model", - input_types=["LanguageModel"], - required=True - ), + FileInput(name="path", display_name="File Path", file_types=["csv"], required=True), + HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), DropdownInput( name="agent_type", display_name="Agent Type", @@ -32,13 +21,7 @@ class CSVAgentComponent(LCAgentComponent): options=["zero-shot-react-description", "openai-functions", "openai-tools"], value="openai-tools", ), - ] def build_agent(self) -> AgentExecutor: - return create_csv_agent( - llm=self.llm, - path=self.path, - agent_type=self.agent_type, - **self.get_agent_kwargs() - ) + return create_csv_agent(llm=self.llm, path=self.path, agent_type=self.agent_type, **self.get_agent_kwargs()) diff --git a/src/backend/base/langflow/components/agents/JsonAgent.py b/src/backend/base/langflow/components/agents/JsonAgent.py index f3832ea8bbb..f79d2dba5e0 100644 --- a/src/backend/base/langflow/components/agents/JsonAgent.py +++ b/src/backend/base/langflow/components/agents/JsonAgent.py @@ -7,9 +7,7 @@ from langchain_community.tools.json.tool import JsonSpec from langflow.base.agents.agent import LCAgentComponent -from langflow.custom import Component -from langflow.inputs import BoolInput, HandleInput, FileInput -from langflow.template import Output +from langflow.inputs import HandleInput, FileInput class JsonAgentComponent(LCAgentComponent): @@ -18,19 +16,10 @@ class JsonAgentComponent(LCAgentComponent): name = "JsonAgent" inputs = LCAgentComponent._base_inputs + [ - FileInput( - name="path", - display_name="File Path", - file_types=["json", "yaml", "yml"], - required=True - ), - HandleInput( - name="llm", - display_name="Language Model", - input_types=["LanguageModel"], - required=True - ) + FileInput(name="path", display_name="File Path", file_types=["json", "yaml", "yml"], required=True), + HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), ] + def build_agent(self) -> AgentExecutor: if self.path.endswith("yaml") or self.path.endswith("yml"): yaml_dict = yaml.load(open(self.path, "r"), Loader=yaml.FullLoader) @@ -39,8 +28,4 @@ def build_agent(self) -> AgentExecutor: spec = JsonSpec.from_file(Path(self.path)) toolkit = JsonToolkit(spec=spec) - return create_json_agent( - llm=self.llm, - toolkit=toolkit, - **self.get_agent_kwargs() - ) \ No newline at end of file + return create_json_agent(llm=self.llm, toolkit=toolkit, **self.get_agent_kwargs()) diff --git a/src/backend/base/langflow/components/agents/OpenAIToolsAgent.py b/src/backend/base/langflow/components/agents/OpenAIToolsAgent.py index 65f8d113ee1..45eafc430e7 100644 --- a/src/backend/base/langflow/components/agents/OpenAIToolsAgent.py +++ b/src/backend/base/langflow/components/agents/OpenAIToolsAgent.py @@ -1,7 +1,7 @@ from langchain.agents import create_openai_tools_agent from langchain_core.prompts import ChatPromptTemplate, PromptTemplate, HumanMessagePromptTemplate -from langflow.base.agents.agent import LCAgentComponent, LCToolsAgentComponent +from langflow.base.agents.agent import LCToolsAgentComponent from langflow.inputs import MultilineInput @@ -20,10 +20,7 @@ class OpenAIToolsAgentComponent(LCToolsAgentComponent): value="You are a helpful assistant", ), MultilineInput( - name="user_prompt", - display_name="Prompt", - info="This prompt must contain 'input' key.", - value="{input}" + name="user_prompt", display_name="Prompt", info="This prompt must contain 'input' key.", value="{input}" ), ] @@ -32,8 +29,8 @@ def creat_agent_runnable(self): raise ValueError("Prompt must contain 'input' key.") messages = [ ("system", self.system_prompt), - HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template=self.user_prompt)), - ("placeholder", "{agent_scratchpad}") + HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=["input"], template=self.user_prompt)), + ("placeholder", "{agent_scratchpad}"), ] prompt = ChatPromptTemplate.from_messages(messages) - return create_openai_tools_agent(self.llm, self.tools, prompt) \ No newline at end of file + return create_openai_tools_agent(self.llm, self.tools, prompt) diff --git a/src/backend/base/langflow/components/agents/OpenAPIAgent.py b/src/backend/base/langflow/components/agents/OpenAPIAgent.py index 2762dc84792..f453ada491c 100644 --- a/src/backend/base/langflow/components/agents/OpenAPIAgent.py +++ b/src/backend/base/langflow/components/agents/OpenAPIAgent.py @@ -3,12 +3,10 @@ import yaml from langchain.agents import AgentExecutor from langchain_community.agent_toolkits import create_openapi_agent -from langchain_community.agent_toolkits.json.toolkit import JsonToolkit from langchain_community.tools.json.tool import JsonSpec -from langchain_community.agent_toolkits.openapi.toolkit import BaseToolkit, OpenAPIToolkit +from langchain_community.agent_toolkits.openapi.toolkit import OpenAPIToolkit from langflow.base.agents.agent import LCAgentComponent -from langflow.custom import Component from langflow.inputs import BoolInput, HandleInput, FileInput from langchain_community.utilities.requests import TextRequestsWrapper @@ -19,25 +17,11 @@ class OpenAPIAgentComponent(LCAgentComponent): name = "OpenAPIAgent" inputs = LCAgentComponent._base_inputs + [ - FileInput( - name="path", - display_name="File Path", - file_types=["json", "yaml", "yml"], - required=True - ), - HandleInput( - name="llm", - display_name="Language Model", - input_types=["LanguageModel"], - required=True - ), - BoolInput( - name="allow_dangerous_requests", - display_name="Allow Dangerous Requests", - value=False, - required=True - ) + FileInput(name="path", display_name="File Path", file_types=["json", "yaml", "yml"], required=True), + HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), + BoolInput(name="allow_dangerous_requests", display_name="Allow Dangerous Requests", value=False, required=True), ] + def build_agent(self) -> AgentExecutor: if self.path.endswith("yaml") or self.path.endswith("yml"): yaml_dict = yaml.load(open(self.path, "r"), Loader=yaml.FullLoader) @@ -55,8 +39,4 @@ def build_agent(self) -> AgentExecutor: agent_args = self.get_agent_kwargs() agent_args["max_iterations"] = agent_args["agent_executor_kwargs"]["max_iterations"] del agent_args["agent_executor_kwargs"]["max_iterations"] - return create_openapi_agent( - llm=self.llm, - toolkit=toolkit, - **agent_args - ) \ No newline at end of file + return create_openapi_agent(llm=self.llm, toolkit=toolkit, **agent_args) diff --git a/src/backend/base/langflow/components/agents/SQLAgent.py b/src/backend/base/langflow/components/agents/SQLAgent.py index 3afef302203..9db94deffde 100644 --- a/src/backend/base/langflow/components/agents/SQLAgent.py +++ b/src/backend/base/langflow/components/agents/SQLAgent.py @@ -13,17 +13,8 @@ class SQLAgentComponent(LCAgentComponent): name = "SQLAgent" inputs = LCAgentComponent._base_inputs + [ - MessageTextInput( - name="database_uri", - display_name="Database URI", - required=True - ), - HandleInput( - name="llm", - display_name="Language Model", - input_types=["LanguageModel"], - required=True - ) + MessageTextInput(name="database_uri", display_name="Database URI", required=True), + HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), ] def build_agent(self) -> AgentExecutor: @@ -32,8 +23,4 @@ def build_agent(self) -> AgentExecutor: agent_args = self.get_agent_kwargs() agent_args["max_iterations"] = agent_args["agent_executor_kwargs"]["max_iterations"] del agent_args["agent_executor_kwargs"]["max_iterations"] - return create_sql_agent( - llm=self.llm, - toolkit=toolkit, - **agent_args - ) \ No newline at end of file + return create_sql_agent(llm=self.llm, toolkit=toolkit, **agent_args) diff --git a/src/backend/base/langflow/components/agents/ToolCallingAgent.py b/src/backend/base/langflow/components/agents/ToolCallingAgent.py index 6294b85a25a..f77d4ac6997 100644 --- a/src/backend/base/langflow/components/agents/ToolCallingAgent.py +++ b/src/backend/base/langflow/components/agents/ToolCallingAgent.py @@ -1,6 +1,6 @@ from langchain.agents import create_tool_calling_agent from langchain_core.prompts import ChatPromptTemplate, PromptTemplate, HumanMessagePromptTemplate -from langflow.base.agents.agent import LCAgentComponent, LCToolsAgentComponent +from langflow.base.agents.agent import LCToolsAgentComponent from langflow.inputs import MultilineInput @@ -19,21 +19,17 @@ class ToolCallingAgentComponent(LCToolsAgentComponent): value="You are a helpful assistant", ), MultilineInput( - name="user_prompt", - display_name="Prompt", - info="This prompt must contain 'input' key.", - value="{input}" + name="user_prompt", display_name="Prompt", info="This prompt must contain 'input' key.", value="{input}" ), ] - def creat_agent_runnable(self): if "input" not in self.user_prompt: raise ValueError("Prompt must contain 'input' key.") messages = [ ("system", self.system_prompt), - HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template=self.user_prompt)), - ("placeholder", "{agent_scratchpad}") + HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=["input"], template=self.user_prompt)), + ("placeholder", "{agent_scratchpad}"), ] prompt = ChatPromptTemplate.from_messages(messages) - return create_tool_calling_agent(self.llm, self.tools, prompt) \ No newline at end of file + return create_tool_calling_agent(self.llm, self.tools, prompt) diff --git a/src/backend/base/langflow/components/agents/VectorStoreAgent.py b/src/backend/base/langflow/components/agents/VectorStoreAgent.py index 9cd52a84843..9a66c08a68b 100644 --- a/src/backend/base/langflow/components/agents/VectorStoreAgent.py +++ b/src/backend/base/langflow/components/agents/VectorStoreAgent.py @@ -1,5 +1,3 @@ -from typing import Callable, Union - from langchain.agents import AgentExecutor, create_vectorstore_agent from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreToolkit from langflow.base.agents.agent import LCAgentComponent @@ -12,21 +10,10 @@ class VectorStoreAgentComponent(LCAgentComponent): name = "VectorStoreAgent" inputs = LCAgentComponent._base_inputs + [ - HandleInput( - name="llm", - display_name="Language Model", - input_types=["LanguageModel"], - required=True - ), - HandleInput( - name="vectorstore", - display_name="Vector Store", - input_types=["VectorStoreInfo"], - required=True - ) + HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), + HandleInput(name="vectorstore", display_name="Vector Store", input_types=["VectorStoreInfo"], required=True), ] def build_agent(self) -> AgentExecutor: toolkit = VectorStoreToolkit(vectorstore_info=self.vectorstore, llm=self.llm) - return create_vectorstore_agent(llm=self.llm, toolkit=toolkit, - **self.get_agent_kwargs()) \ No newline at end of file + return create_vectorstore_agent(llm=self.llm, toolkit=toolkit, **self.get_agent_kwargs()) diff --git a/src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py b/src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py index aa6f397ee9a..727379fc963 100644 --- a/src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py +++ b/src/backend/base/langflow/components/agents/VectorStoreRouterAgent.py @@ -1,8 +1,8 @@ from langchain.agents import create_vectorstore_router_agent -from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit, VectorStoreInfo +from langchain.agents.agent_toolkits.vectorstore.toolkit import VectorStoreRouterToolkit from langflow.base.agents.agent import LCAgentComponent -from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent +from langchain.agents import AgentExecutor from langflow.inputs import HandleInput @@ -12,22 +12,16 @@ class VectorStoreRouterAgentComponent(LCAgentComponent): name = "VectorStoreRouterAgent" inputs = LCAgentComponent._base_inputs + [ - HandleInput( - name="llm", - display_name="Language Model", - input_types=["LanguageModel"], - required=True - ), + HandleInput(name="llm", display_name="Language Model", input_types=["LanguageModel"], required=True), HandleInput( name="vectorstores", display_name="Vector Stores", input_types=["VectorStoreInfo"], is_list=True, - required=True - ) + required=True, + ), ] def build_agent(self) -> AgentExecutor: toolkit = VectorStoreRouterToolkit(vectorstores=self.vectorstores, llm=self.llm) - return create_vectorstore_router_agent(llm=self.llm, toolkit=toolkit, - **self.get_agent_kwargs()) \ No newline at end of file + return create_vectorstore_router_agent(llm=self.llm, toolkit=toolkit, **self.get_agent_kwargs()) diff --git a/src/backend/base/langflow/components/agents/XMLAgent.py b/src/backend/base/langflow/components/agents/XMLAgent.py index 6d1804f5c90..cc8a50e49e5 100644 --- a/src/backend/base/langflow/components/agents/XMLAgent.py +++ b/src/backend/base/langflow/components/agents/XMLAgent.py @@ -1,7 +1,7 @@ from langchain.agents import create_xml_agent from langchain_core.prompts import ChatPromptTemplate, PromptTemplate, HumanMessagePromptTemplate -from langflow.base.agents.agent import LCAgentComponent, LCToolsAgentComponent +from langflow.base.agents.agent import LCToolsAgentComponent from langflow.inputs import MultilineInput @@ -40,13 +40,13 @@ class XMLAgentComponent(LCToolsAgentComponent): Question: {input} {agent_scratchpad} - """ + """, ), ] def creat_agent_runnable(self): messages = [ - HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], template=self.user_prompt)) + HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=["input"], template=self.user_prompt)) ] prompt = ChatPromptTemplate.from_messages(messages) - return create_xml_agent(self.llm, self.tools, prompt) \ No newline at end of file + return create_xml_agent(self.llm, self.tools, prompt) diff --git a/src/backend/base/langflow/components/prototypes/RunnableExecutor.py b/src/backend/base/langflow/components/prototypes/RunnableExecutor.py index 2ddd130f961..8aec1886f95 100644 --- a/src/backend/base/langflow/components/prototypes/RunnableExecutor.py +++ b/src/backend/base/langflow/components/prototypes/RunnableExecutor.py @@ -11,16 +11,12 @@ class RunnableExecComponent(Component): beta: bool = True inputs = [ - MessageTextInput( - name="input_value", - display_name="Input", - required=True - ), + MessageTextInput(name="input_value", display_name="Input", required=True), HandleInput( name="runnable", display_name="Agent Executor", input_types=["Chain", "AgentExecutor", "Agent", "Runnable"], - required=True + required=True, ), MessageTextInput( name="input_key", diff --git a/src/backend/base/langflow/components/toolkits/VectorStoreInfo.py b/src/backend/base/langflow/components/toolkits/VectorStoreInfo.py index 796c4bb8ef6..41ab7ef7364 100644 --- a/src/backend/base/langflow/components/toolkits/VectorStoreInfo.py +++ b/src/backend/base/langflow/components/toolkits/VectorStoreInfo.py @@ -27,7 +27,7 @@ class VectorStoreInfoComponent(Component): display_name="Vector Store", input_types=["VectorStore"], required=True, - ) + ), ] outputs = [ @@ -39,6 +39,6 @@ def build_info(self) -> VectorStoreInfo: "name": self.vectorstore_name, "description": self.vectorstore_description, } - return VectorStoreInfo(vectorstore=self.input_vectorstore, - description=self.vectorstore_description, - name=self.vectorstore_name) + return VectorStoreInfo( + vectorstore=self.input_vectorstore, description=self.vectorstore_description, name=self.vectorstore_name + ) From 7f94fd41d4b0b117c5a969165a76697ee53f3879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Boschi?= Date: Mon, 8 Jul 2024 18:25:15 +0200 Subject: [PATCH 5/5] fix mypy --- .../base/langflow/base/agents/agent.py | 2 +- .../components/deactivated/AgentComponent.py | 186 ------------------ .../components/deactivated/__init__.py | 2 - .../langflow/components/toolkits/__init__.py | 8 - 4 files changed, 1 insertion(+), 197 deletions(-) delete mode 100644 src/backend/base/langflow/components/deactivated/AgentComponent.py diff --git a/src/backend/base/langflow/base/agents/agent.py b/src/backend/base/langflow/base/agents/agent.py index e6b353058ca..5475e77e88e 100644 --- a/src/backend/base/langflow/base/agents/agent.py +++ b/src/backend/base/langflow/base/agents/agent.py @@ -80,7 +80,7 @@ class LCToolsAgentComponent(LCAgentComponent): def build_agent(self) -> AgentExecutor: agent = self.creat_agent_runnable() return AgentExecutor.from_agent_and_tools( - agent=RunnableAgent(runnable=agent, input_keys_arg=["input"], output_keys_arg=["output"]), + agent=RunnableAgent(runnable=agent, input_keys_arg=["input"], return_keys_arg=["output"]), tools=self.tools, **self.get_agent_kwargs(flatten=True), ) diff --git a/src/backend/base/langflow/components/deactivated/AgentComponent.py b/src/backend/base/langflow/components/deactivated/AgentComponent.py deleted file mode 100644 index a89213feadc..00000000000 --- a/src/backend/base/langflow/components/deactivated/AgentComponent.py +++ /dev/null @@ -1,186 +0,0 @@ -from typing import Any, List, Optional, cast - -from langchain_core.prompts import ChatPromptTemplate -from langchain_core.prompts.chat import HumanMessagePromptTemplate, SystemMessagePromptTemplate - -from langflow.base.agents.agent import LCAgentComponent -from langflow.base.agents.utils import AGENTS, AgentSpec, get_agents_list -from langflow.field_typing import LanguageModel, Text, Tool -from langflow.schema import Data -from langflow.schema.dotdict import dotdict - - -class AgentComponent(LCAgentComponent): - display_name = "Agent" - description = "Run any LangChain agent using a simplified interface." - field_order = [ - "agent_name", - "llm", - "tools", - "prompt", - "tool_template", - "handle_parsing_errors", - "memory", - "input_value", - ] - name = "AgentComponent" - - def build_config(self): - return { - "agent_name": { - "display_name": "Agent", - "info": "The agent to use.", - "refresh_button": True, - "real_time_refresh": True, - "options": get_agents_list(), - }, - "llm": {"display_name": "LLM"}, - "tools": {"display_name": "Tools"}, - "user_prompt": { - "display_name": "Prompt", - "multiline": True, - "info": "This prompt must contain 'tools' and 'agent_scratchpad' keys.", - }, - "system_message": { - "display_name": "System Message", - "info": "System message to be passed to the LLM.", - "advanced": True, - }, - "tool_template": { - "display_name": "Tool Template", - "info": "Template for rendering tools in the prompt. Tools have 'name' and 'description' keys.", - "advanced": True, - }, - "handle_parsing_errors": { - "display_name": "Handle Parsing Errors", - "info": "If True, the agent will handle parsing errors. If False, the agent will raise an error.", - "advanced": True, - }, - "message_history": { - "display_name": "Message History", - "info": "Message history to pass to the agent.", - }, - "input_value": { - "display_name": "Input", - "info": "Input text to pass to the agent.", - }, - "langchain_hub_api_key": { - "display_name": "LangChain Hub API Key", - "info": "API key to use for LangChain Hub. If provided, prompts will be fetched from LangChain Hub.", - "advanced": True, - }, - } - - def get_system_and_user_message_from_prompt(self, prompt: Any): - """ - Extracts the system message and user prompt from a given prompt object. - - Args: - prompt (Any): The prompt object from which to extract the system message and user prompt. - - Returns: - Tuple[Optional[str], Optional[str]]: A tuple containing the system message and user prompt. - If the prompt object does not have any messages, both values will be None. - """ - if hasattr(prompt, "messages"): - system_message = None - user_prompt = None - for message in prompt.messages: - if isinstance(message, SystemMessagePromptTemplate): - s_prompt = message.prompt - if isinstance(s_prompt, list): - s_template = " ".join([cast(str, s.template) for s in s_prompt if hasattr(s, "template")]) - elif hasattr(s_prompt, "template"): - s_template = s_prompt.template - system_message = s_template - elif isinstance(message, HumanMessagePromptTemplate): - h_prompt = message.prompt - if isinstance(h_prompt, list): - h_template = " ".join([cast(str, h.template) for h in h_prompt if hasattr(h, "template")]) - elif hasattr(h_prompt, "template"): - h_template = h_prompt.template - user_prompt = h_template - return system_message, user_prompt - return None, None - - def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None): - """ - Updates the build configuration based on the provided field value and field name. - - Args: - build_config (dotdict): The build configuration to be updated. - field_value (Any): The value of the field being updated. - field_name (Text | None, optional): The name of the field being updated. Defaults to None. - - Returns: - dotdict: The updated build configuration. - """ - if field_name == "agent": - build_config["agent"]["options"] = get_agents_list() - if field_value in AGENTS: - # if langchain_hub_api_key is provided, fetch the prompt from LangChain Hub - if build_config["langchain_hub_api_key"]["value"] and AGENTS[field_value].hub_repo: - from langchain import hub - - hub_repo: str | None = AGENTS[field_value].hub_repo - if hub_repo: - hub_api_key: str = build_config["langchain_hub_api_key"]["value"] - prompt = hub.pull(hub_repo, api_key=hub_api_key) - system_message, user_prompt = self.get_system_and_user_message_from_prompt(prompt) - if system_message: - build_config["system_message"]["value"] = system_message - if user_prompt: - build_config["user_prompt"]["value"] = user_prompt - - if AGENTS[field_value].prompt: - build_config["user_prompt"]["value"] = AGENTS[field_value].prompt - else: - build_config["user_prompt"]["value"] = "{input}" - fields = AGENTS[field_value].fields - for field in ["llm", "tools", "prompt", "tools_renderer"]: - if field not in fields: - build_config[field]["show"] = False - return build_config - - async def build( - self, - agent_name: str, - input_value: str, - llm: LanguageModel, - tools: List[Tool], - system_message: str = "You are a helpful assistant. Help the user answer any questions.", - user_prompt: str = "{input}", - message_history: Optional[List[Data]] = None, - tool_template: str = "{name}: {description}", - handle_parsing_errors: bool = True, - ) -> Text: - agent_spec: Optional[AgentSpec] = AGENTS.get(agent_name) - if agent_spec is None: - raise ValueError(f"{agent_name} not found.") - - def render_tool_description(tools): - return "\n".join( - [tool_template.format(name=tool.name, description=tool.description, args=tool.args) for tool in tools] - ) - - messages = [ - ("system", system_message), - ( - "placeholder", - "{chat_history}", - ), - ("human", user_prompt), - ("placeholder", "{agent_scratchpad}"), - ] - prompt = ChatPromptTemplate.from_messages(messages) - agent_func = agent_spec.func - agent = agent_func(llm, tools, prompt, render_tool_description, True) - result = await self.run_agent( - agent=agent, - inputs=input_value, - tools=tools, - message_history=message_history, - handle_parsing_errors=handle_parsing_errors, - ) - self.status = result - return result diff --git a/src/backend/base/langflow/components/deactivated/__init__.py b/src/backend/base/langflow/components/deactivated/__init__.py index 51ef2e465b9..8be439d874b 100644 --- a/src/backend/base/langflow/components/deactivated/__init__.py +++ b/src/backend/base/langflow/components/deactivated/__init__.py @@ -1,4 +1,3 @@ -from .AgentComponent import AgentComponent from .ExtractKeyFromData import ExtractKeyFromDataComponent from .ListFlows import ListFlowsComponent from .MergeData import MergeDataComponent @@ -6,7 +5,6 @@ from .SubFlow import SubFlowComponent __all__ = [ - "AgentComponent", "ConditionalRouterComponent", "ExtractKeyFromDataComponent", "FlowToolComponent", diff --git a/src/backend/base/langflow/components/toolkits/__init__.py b/src/backend/base/langflow/components/toolkits/__init__.py index 189b4315995..abded990c63 100644 --- a/src/backend/base/langflow/components/toolkits/__init__.py +++ b/src/backend/base/langflow/components/toolkits/__init__.py @@ -1,15 +1,7 @@ -from .JsonToolkit import JsonToolkitComponent from .Metaphor import MetaphorToolkit -from .OpenAPIToolkit import OpenAPIToolkitComponent from .VectorStoreInfo import VectorStoreInfoComponent -from .VectorStoreRouterToolkit import VectorStoreRouterToolkitComponent -from .VectorStoreToolkit import VectorStoreToolkitComponent __all__ = [ - "JsonToolkitComponent", "MetaphorToolkit", - "OpenAPIToolkitComponent", "VectorStoreInfoComponent", - "VectorStoreRouterToolkitComponent", - "VectorStoreToolkitComponent", ]