refactor(FlowTool.py): update FlowToolComponent class to inherit from LCToolComponent (#3048)

* refactor(utils.py): simplify data processing logic in build_data_from_result_data function for better readability and maintainability

* feat: set default output type to "chat" in run_flow function

* refactor(FlowTool.py): refactor FlowToolComponent class to inherit from LCToolComponent

* Fixed Flow as Tool component

* Fixed FlowTool to only output tool and removed async function def

* [autofix.ci] apply automated fixes

* Fixed lint

---------

Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Co-authored-by: Lucas Oliveira <lucas.edu.oli@hotmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Gabriel Luiz Freitas Almeida 2024-07-30 17:47:35 -03:00 • committed by GitHub
commit 8bc45b9ee2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 48 additions and 43 deletions

View file

@ -4,6 +4,7 @@ from loguru import logger
from langflow.graph.schema import ResultData, RunOutputs from langflow.graph.schema import ResultData, RunOutputs
from langflow.schema import Data from langflow.schema import Data
from langflow.schema.message import Message
def build_data_from_run_outputs(run_outputs: RunOutputs) -> List[Data]: def build_data_from_run_outputs(run_outputs: RunOutputs) -> List[Data]:
@ -65,14 +66,17 @@ def build_data_from_result_data(result_data: ResultData, get_final_results_only:
else: else:
return [] return []
for message in messages: # type: ignore if isinstance(result_data.results, dict):
message_dict = message if isinstance(message, dict) else message.model_dump() for name, result in result_data.results.items():
if get_final_results_only: dataobj: Data | Message | None = None
result_data_dict = result_data.model_dump() if isinstance(result, Message):
results = result_data_dict.get("results", {}) dataobj = result
inner_result = results.get("result", {}) else:
record = Data(data={"result": inner_result, "message": message_dict}, text_key="result") dataobj = Data(data=result, text_key=name)
data.append(record)
data.append(dataobj)
else:
data.append(Data(data=result_data.results))
return data return data
@ -88,5 +92,5 @@ def format_flow_output_data(data: List[Data]) -> str:
""" """
result = "Flow run output:\n" result = "Flow run output:\n"
results = "\n".join([value.result for value in data if value.data["message"]]) results = "\n".join([value.get_text() if hasattr(value, "get_text") else str(value) for value in data])
return result + results return result + results

View file

@ -1,17 +1,17 @@
from typing import Any, List, Optional from typing import Any, List, Optional
from loguru import logger
from langflow.base.langchain_utilities.model import LCToolComponent
from langflow.base.tools.flow_tool import FlowTool from langflow.base.tools.flow_tool import FlowTool
from langflow.custom import CustomComponent
from langflow.field_typing import Tool from langflow.field_typing import Tool
from langflow.graph.graph.base import Graph from langflow.graph.graph.base import Graph
from langflow.helpers.flow import get_flow_inputs from langflow.helpers.flow import get_flow_inputs
from langflow.io import BoolInput, DropdownInput, StrInput, Output
from langflow.schema import Data from langflow.schema import Data
from langflow.schema.dotdict import dotdict from langflow.schema.dotdict import dotdict
class FlowToolComponent(CustomComponent): class FlowToolComponent(LCToolComponent):
display_name = "Flow as Tool" display_name = "Flow as Tool"
description = "Construct a Tool from a function that runs the loaded Flow." description = "Construct a Tool from a function that runs the loaded Flow."
field_order = ["flow_name", "name", "description", "return_direct"] field_order = ["flow_name", "name", "description", "return_direct"]
@ -40,48 +40,49 @@ class FlowToolComponent(CustomComponent):
return None return None
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = 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": if field_name == "flow_name":
build_config["flow_name"]["options"] = self.get_flow_names() build_config["flow_name"]["options"] = self.get_flow_names()
return build_config return build_config
def build_config(self): inputs = [
return { DropdownInput(
"flow_name": { name="flow_name", display_name="Flow Name", info="The name of the flow to run.", refresh_button=True
"display_name": "Flow Name", ),
"info": "The name of the flow to run.", StrInput(
"options": [], name="name",
"real_time_refresh": True, display_name="Name",
"refresh_button": True, info="The name of the tool.",
}, ),
"name": { StrInput(
"display_name": "Name", name="description",
"description": "The name of the tool.", display_name="Description",
}, info="The description of the tool.",
"description": { ),
"display_name": "Description", BoolInput(
"description": "The description of the tool.", name="return_direct",
}, display_name="Return Direct",
"return_direct": { info="Return the result directly from the Tool.",
"display_name": "Return Direct", advanced=True,
"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: outputs = [
Output(name="api_build_tool", display_name="Tool", method="build_tool"),
]
def build_tool(self) -> Tool:
FlowTool.update_forward_refs() FlowTool.update_forward_refs()
flow_data = self.get_flow(flow_name) flow_data = self.get_flow(self.flow_name)
if not flow_data: if not flow_data:
raise ValueError("Flow not found.") raise ValueError("Flow not found.")
graph = Graph.from_payload(flow_data.data["data"]) graph = Graph.from_payload(flow_data.data["data"])
inputs = get_flow_inputs(graph) inputs = get_flow_inputs(graph)
tool = FlowTool( tool = FlowTool(
name=name, name=self.name,
description=description, description=self.description,
graph=graph, graph=graph,
return_direct=return_direct, return_direct=self.return_direct,
inputs=inputs, inputs=inputs,
flow_id=str(flow_data.id), flow_id=str(flow_data.id),
user_id=str(self._user_id), user_id=str(self._user_id),

View file

@ -480,7 +480,7 @@ class CustomComponent(BaseComponent):
inputs: Optional[Union[dict, List[dict]]] = None, inputs: Optional[Union[dict, List[dict]]] = None,
flow_id: Optional[str] = None, flow_id: Optional[str] = None,
flow_name: Optional[str] = None, flow_name: Optional[str] = None,
output_type: Optional[str] = None, output_type: Optional[str] = "chat",
tweaks: Optional[dict] = None, tweaks: Optional[dict] = None,
) -> Any: ) -> Any:
return await run_flow( return await run_flow(

View file

@ -71,7 +71,7 @@ async def run_flow(
tweaks: Optional[dict] = None, tweaks: Optional[dict] = None,
flow_id: Optional[str] = None, flow_id: Optional[str] = None,
flow_name: Optional[str] = None, flow_name: Optional[str] = None,
output_type: Optional[str] = None, output_type: Optional[str] = "chat",
user_id: Optional[str] = None, user_id: Optional[str] = None,
) -> List[RunOutputs]: ) -> List[RunOutputs]:
if user_id is None: if user_id is None: