diff --git a/src/backend/base/langflow/api/v1/chat.py b/src/backend/base/langflow/api/v1/chat.py index 214d6d158..613a2fc51 100644 --- a/src/backend/base/langflow/api/v1/chat.py +++ b/src/backend/base/langflow/api/v1/chat.py @@ -1,7 +1,7 @@ import time import uuid from functools import partial -from typing import TYPE_CHECKING, Annotated, Callable, Optional +from typing import TYPE_CHECKING, Annotated, Optional from fastapi import APIRouter, BackgroundTasks, Body, Depends, HTTPException from fastapi.responses import StreamingResponse diff --git a/src/backend/base/langflow/base/agents/agent.py b/src/backend/base/langflow/base/agents/agent.py index d995280f4..28767a59a 100644 --- a/src/backend/base/langflow/base/agents/agent.py +++ b/src/backend/base/langflow/base/agents/agent.py @@ -1,10 +1,11 @@ -from typing import List, Optional, Union +from typing import List, Union + +from langchain.agents import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent -from langchain.agents.agent import AgentExecutor, BaseMultiActionAgent, BaseSingleActionAgent from langchain_core.runnables import Runnable +from langflow.custom import CustomComponent from langflow.field_typing import BaseMemory, Text, Tool -from langflow.interface.custom.custom_component import CustomComponent class LCAgentComponent(CustomComponent): @@ -44,7 +45,7 @@ class LCAgentComponent(CustomComponent): inputs: str, input_variables: list[str], tools: List[Tool], - memory: Optional[BaseMemory] = None, + memory: BaseMemory = None, handle_parsing_errors: bool = True, output_key: str = "output", ) -> Text: @@ -52,11 +53,7 @@ class LCAgentComponent(CustomComponent): runnable = agent else: runnable = AgentExecutor.from_agent_and_tools( - agent=agent, # type: ignore - tools=tools, - verbose=True, - memory=memory, - handle_parsing_errors=handle_parsing_errors, + agent=agent, tools=tools, verbose=True, memory=memory, handle_parsing_errors=handle_parsing_errors ) input_dict = {"input": inputs} for var in input_variables: @@ -72,5 +69,4 @@ class LCAgentComponent(CustomComponent): else: raise ValueError("Output key not found in result. Tried 'output'.") - output: str = result.get("output") - return output + return result.get("output") diff --git a/src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py b/src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py index c902e7faf..a7fc838b3 100644 --- a/src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py +++ b/src/backend/base/langflow/components/embeddings/OpenAIEmbeddings.py @@ -1,7 +1,6 @@ from typing import Any, Callable, Dict, List, Optional, Union from langchain_openai.embeddings.base import OpenAIEmbeddings -from pydantic.v1.types import SecretStr from langflow.field_typing import NestedDict from langflow.interface.custom.custom_component import CustomComponent diff --git a/src/backend/base/langflow/components/experimental/FlowTool.py b/src/backend/base/langflow/components/experimental/FlowTool.py index ac48a0f03..541341d85 100644 --- a/src/backend/base/langflow/components/experimental/FlowTool.py +++ b/src/backend/base/langflow/components/experimental/FlowTool.py @@ -1,4 +1,4 @@ -from typing import Any, List, Optional +from typing import Any, List, Optional, Text from langchain_core.tools import StructuredTool from loguru import logger @@ -8,7 +8,6 @@ from langflow.field_typing import Tool from langflow.graph.graph.base import Graph from langflow.helpers.flow import build_function_and_schema from langflow.schema.dotdict import dotdict -from langflow.schema.schema import Record class FlowToolComponent(CustomComponent): @@ -20,7 +19,7 @@ class FlowToolComponent(CustomComponent): flow_records = self.list_flows() return [flow_record.data["name"] for flow_record in flow_records] - def get_flow(self, flow_name: str) -> Optional[Record]: + def get_flow(self, flow_name: str) -> Optional[Text]: """ Retrieves a flow by its name. @@ -83,4 +82,4 @@ class FlowToolComponent(CustomComponent): description_repr = repr(tool.description).strip("'") args_str = "\n".join([f"- {arg_name}: {arg_data['description']}" for arg_name, arg_data in tool.args.items()]) self.status = f"{description_repr}\nArguments:\n{args_str}" - return tool # type: ignore + return tool diff --git a/src/backend/base/langflow/components/experimental/SubFlow.py b/src/backend/base/langflow/components/experimental/SubFlow.py index 7a45bb6e9..9f9abded3 100644 --- a/src/backend/base/langflow/components/experimental/SubFlow.py +++ b/src/backend/base/langflow/components/experimental/SubFlow.py @@ -1,10 +1,11 @@ -from typing import Any, List, Optional, Tuple +from typing import Any, List, Optional from loguru import logger from langflow.custom import CustomComponent from langflow.graph.graph.base import Graph from langflow.graph.schema import ResultData, RunOutputs +from langflow.graph.vertex.base import Vertex from langflow.schema import Record from langflow.schema.dotdict import dotdict from langflow.template.field.base import TemplateField @@ -50,7 +51,7 @@ class SubFlowComponent(CustomComponent): return build_config - def get_flow_inputs(self, graph: Graph) -> List[Record]: + def get_flow_inputs(self, graph: Graph) -> List[Vertex]: inputs = [] for vertex in graph.vertices: if vertex.is_input: @@ -58,13 +59,13 @@ class SubFlowComponent(CustomComponent): logger.debug(inputs) return inputs - def add_inputs_to_build_config(self, inputs: List[Tuple], build_config: dotdict): + def add_inputs_to_build_config(self, inputs: List[Vertex], build_config: dotdict): new_fields: list[TemplateField] = [] - for input_id, input_display_name, input_description in inputs: + for vertex in inputs: field = TemplateField( - display_name=input_display_name, - name=input_id, - info=input_description, + display_name=vertex.display_name, + name=vertex.id, + info=vertex.description, field_type="str", default=None, ) diff --git a/src/backend/base/langflow/interface/tools/base.py b/src/backend/base/langflow/interface/tools/base.py index 2506c0170..ddaccb4bb 100644 --- a/src/backend/base/langflow/interface/tools/base.py +++ b/src/backend/base/langflow/interface/tools/base.py @@ -5,8 +5,6 @@ from langflow.interface.base import LangChainTypeCreator from langflow.interface.tools.constants import ALL_TOOLS_NAMES, CUSTOM_TOOLS, FILE_TOOLS, OTHER_TOOLS from langflow.interface.tools.util import get_tool_params from langflow.legacy_custom import customs -from langflow.interface.tools.util import get_tool_params -from langflow.legacy_custom import customs from langflow.services.deps import get_settings_service from langflow.template.field.base import TemplateField from langflow.template.template.base import Template diff --git a/src/backend/langflow/base/agents/agent.py b/src/backend/langflow/base/agents/agent.py deleted file mode 100644 index b0c61f6e1..000000000 --- a/src/backend/langflow/base/agents/agent.py +++ /dev/null @@ -1,70 +0,0 @@ -from typing import List, Union - -from langchain.agents import (AgentExecutor, BaseMultiActionAgent, - -from langflow.custom import CustomComponent -from langflow.field_typing import BaseMemory, Text, Tool - - -class LCAgentComponent(CustomComponent): - def build_config(self): - 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.", - }, - } - - async def run_agent( - self, - agent: Union[BaseSingleActionAgent, BaseMultiActionAgent, AgentExecutor], - inputs: str, - input_variables: list[str], - tools: List[Tool], - memory: BaseMemory = 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, tools=tools, verbose=True, memory=memory, handle_parsing_errors=handle_parsing_errors - ) - input_dict = {"input": inputs} - for var in input_variables: - if var not in ["agent_scratchpad", "input"]: - input_dict[var] = "" - result = await runnable.ainvoke(input_dict) - self.status = result - if output_key in result: - return 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 result.get("output") diff --git a/src/backend/langflow/components/experimental/FlowTool.py b/src/backend/langflow/components/experimental/FlowTool.py deleted file mode 100644 index 6dd3e4fa3..000000000 --- a/src/backend/langflow/components/experimental/FlowTool.py +++ /dev/null @@ -1,84 +0,0 @@ -from typing import Any, List, Optional, Text - -from langchain_core.tools import StructuredTool -from langflow.custom import CustomComponent -from langflow.field_typing import Tool -from langflow.graph.graph.base import Graph -from langflow.helpers.flow import build_function_and_schema -from langflow.schema.dotdict import dotdict -from loguru import logger - - -class FlowToolComponent(CustomComponent): - display_name = "Flow as Tool" - description = "Construct a Tool from a function that runs the loaded Flow." - field_order = ["flow_name", "name", "description", "return_direct"] - - def get_flow_names(self) -> List[str]: - flow_records = self.list_flows() - return [flow_record.data["name"] for flow_record in flow_records] - - def get_flow(self, flow_name: str) -> Optional[Text]: - """ - Retrieves a flow by its name. - - Args: - flow_name (str): The name of the flow to retrieve. - - Returns: - Optional[Text]: The flow record if found, None otherwise. - """ - flow_records = self.list_flows() - for flow_record in flow_records: - if flow_record.data["name"] == flow_name: - return flow_record - return None - - def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None): - logger.debug(f"Updating build config with field value {field_value} and field name {field_name}") - if field_name == "flow_name": - build_config["flow_name"]["options"] = self.get_flow_names() - - return build_config - - def build_config(self): - return { - "flow_name": { - "display_name": "Flow Name", - "info": "The name of the flow to run.", - "options": [], - "real_time_refresh": True, - "refresh_button": True, - }, - "name": { - "display_name": "Name", - "description": "The name of the tool.", - }, - "description": { - "display_name": "Description", - "description": "The description of the tool.", - }, - "return_direct": { - "display_name": "Return Direct", - "description": "Return the result directly from the Tool.", - "advanced": True, - }, - } - - async def build(self, flow_name: str, name: str, description: str, return_direct: bool = False) -> Tool: - flow_record = self.get_flow(flow_name) - if not flow_record: - raise ValueError("Flow not found.") - graph = Graph.from_payload(flow_record.data["data"]) - dynamic_flow_function, schema = build_function_and_schema(flow_record, graph) - tool = StructuredTool.from_function( - coroutine=dynamic_flow_function, - name=name, - description=description, - return_direct=return_direct, - args_schema=schema, - ) - description_repr = repr(tool.description).strip("'") - args_str = "\n".join([f"- {arg_name}: {arg_data['description']}" for arg_name, arg_data in tool.args.items()]) - self.status = f"{description_repr}\nArguments:\n{args_str}" - return tool diff --git a/src/backend/langflow/components/experimental/Schema.py b/src/backend/langflow/components/experimental/Schema.py deleted file mode 100644 index 72cbec23e..000000000 --- a/src/backend/langflow/components/experimental/Schema.py +++ /dev/null @@ -1,25 +0,0 @@ -from langflow.custom import CustomComponent - - -class SchemaComponent(CustomComponent): - display_name = "Schema" - description = "Construct a Schema from a list of fields." - - def build_config(self): - return { - "fields": { - "display_name": "Fields", - "info": "The fields to include in the schema.", - }, - "name": { - "display_name": "Name", - "info": "The name of the schema.", - }, - } - - def build(self, name: str, fields: list[dict]): - # The idea for this component is to use create_model from pydantic to create a schema - # from a list of fields. This will be useful for creating schemas for the flow tool. - pass - - # field is a simple list of dictionaries with the field name and diff --git a/src/backend/langflow/components/tools/SearchAPITool.py b/src/backend/langflow/components/tools/SearchAPITool.py deleted file mode 100644 index 2ecee90e7..000000000 --- a/src/backend/langflow/components/tools/SearchAPITool.py +++ /dev/null @@ -1,36 +0,0 @@ -from langchain_community.tools.searchapi import SearchAPIRun -from langchain_community.utilities.searchapi import SearchApiAPIWrapper -from langflow.custom import CustomComponent -from langflow.field_typing import Tool - - -class SearchApiToolComponent(CustomComponent): - display_name: str = "SearchApi Tool" - description: str = "Real-time search engine results API." - documentation: str = "https://www.searchapi.io/docs/google" - field_config = { - "engine": { - "display_name": "Engine", - "field_type": "str", - "info": "The search engine to use.", - }, - "api_key": { - "display_name": "API Key", - "field_type": "str", - "required": True, - "password": True, - "info": "The API key to use SearchApi.", - }, - } - - def build( - self, - engine: str, - api_key: str, - ) -> Tool: - search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key) - - tool = SearchAPIRun(api_wrapper=search_api_wrapper) - - self.status = tool - return tool diff --git a/src/backend/langflow/base/agents/__init__.py b/src/backend/langflow/py.typed similarity index 100% rename from src/backend/langflow/base/agents/__init__.py rename to src/backend/langflow/py.typed diff --git a/src/backend/base/langflow/version.py b/src/backend/langflow/version.py similarity index 100% rename from src/backend/base/langflow/version.py rename to src/backend/langflow/version.py