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.schema import Data
from langflow.schema.message import Message
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:
return []
for message in messages: # type: ignore
message_dict = message if isinstance(message, dict) else message.model_dump()
if get_final_results_only:
result_data_dict = result_data.model_dump()
results = result_data_dict.get("results", {})
inner_result = results.get("result", {})
record = Data(data={"result": inner_result, "message": message_dict}, text_key="result")
data.append(record)
if isinstance(result_data.results, dict):
for name, result in result_data.results.items():
dataobj: Data | Message | None = None
if isinstance(result, Message):
dataobj = result
else:
dataobj = Data(data=result, text_key=name)
data.append(dataobj)
else:
data.append(Data(data=result_data.results))
return data
@ -88,5 +92,5 @@ def format_flow_output_data(data: List[Data]) -> str:
"""
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

View file

@ -1,17 +1,17 @@
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.custom import CustomComponent
from langflow.field_typing import Tool
from langflow.graph.graph.base import Graph
from langflow.helpers.flow import get_flow_inputs
from langflow.io import BoolInput, DropdownInput, StrInput, Output
from langflow.schema import Data
from langflow.schema.dotdict import dotdict
class FlowToolComponent(CustomComponent):
class FlowToolComponent(LCToolComponent):
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"]
@ -40,48 +40,49 @@ class FlowToolComponent(CustomComponent):
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,
},
}
inputs = [
DropdownInput(
name="flow_name", display_name="Flow Name", info="The name of the flow to run.", refresh_button=True
),
StrInput(
name="name",
display_name="Name",
info="The name of the tool.",
),
StrInput(
name="description",
display_name="Description",
info="The description of the tool.",
),
BoolInput(
name="return_direct",
display_name="Return Direct",
info="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()
flow_data = self.get_flow(flow_name)
flow_data = self.get_flow(self.flow_name)
if not flow_data:
raise ValueError("Flow not found.")
graph = Graph.from_payload(flow_data.data["data"])
inputs = get_flow_inputs(graph)
tool = FlowTool(
name=name,
description=description,
name=self.name,
description=self.description,
graph=graph,
return_direct=return_direct,
return_direct=self.return_direct,
inputs=inputs,
flow_id=str(flow_data.id),
user_id=str(self._user_id),

View file

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

View file

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