Add new files and modify existing files
This commit is contained in:
parent
827d6befec
commit
73a23ca096
12 changed files with 19 additions and 241 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
from functools import partial
|
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 import APIRouter, BackgroundTasks, Body, Depends, HTTPException
|
||||||
from fastapi.responses import StreamingResponse
|
from fastapi.responses import StreamingResponse
|
||||||
|
|
|
||||||
|
|
@ -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 langchain_core.runnables import Runnable
|
||||||
|
|
||||||
|
from langflow.custom import CustomComponent
|
||||||
from langflow.field_typing import BaseMemory, Text, Tool
|
from langflow.field_typing import BaseMemory, Text, Tool
|
||||||
from langflow.interface.custom.custom_component import CustomComponent
|
|
||||||
|
|
||||||
|
|
||||||
class LCAgentComponent(CustomComponent):
|
class LCAgentComponent(CustomComponent):
|
||||||
|
|
@ -44,7 +45,7 @@ class LCAgentComponent(CustomComponent):
|
||||||
inputs: str,
|
inputs: str,
|
||||||
input_variables: list[str],
|
input_variables: list[str],
|
||||||
tools: List[Tool],
|
tools: List[Tool],
|
||||||
memory: Optional[BaseMemory] = None,
|
memory: BaseMemory = None,
|
||||||
handle_parsing_errors: bool = True,
|
handle_parsing_errors: bool = True,
|
||||||
output_key: str = "output",
|
output_key: str = "output",
|
||||||
) -> Text:
|
) -> Text:
|
||||||
|
|
@ -52,11 +53,7 @@ class LCAgentComponent(CustomComponent):
|
||||||
runnable = agent
|
runnable = agent
|
||||||
else:
|
else:
|
||||||
runnable = AgentExecutor.from_agent_and_tools(
|
runnable = AgentExecutor.from_agent_and_tools(
|
||||||
agent=agent, # type: ignore
|
agent=agent, tools=tools, verbose=True, memory=memory, handle_parsing_errors=handle_parsing_errors
|
||||||
tools=tools,
|
|
||||||
verbose=True,
|
|
||||||
memory=memory,
|
|
||||||
handle_parsing_errors=handle_parsing_errors,
|
|
||||||
)
|
)
|
||||||
input_dict = {"input": inputs}
|
input_dict = {"input": inputs}
|
||||||
for var in input_variables:
|
for var in input_variables:
|
||||||
|
|
@ -72,5 +69,4 @@ class LCAgentComponent(CustomComponent):
|
||||||
else:
|
else:
|
||||||
raise ValueError("Output key not found in result. Tried 'output'.")
|
raise ValueError("Output key not found in result. Tried 'output'.")
|
||||||
|
|
||||||
output: str = result.get("output")
|
return result.get("output")
|
||||||
return output
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
from typing import Any, Callable, Dict, List, Optional, Union
|
from typing import Any, Callable, Dict, List, Optional, Union
|
||||||
|
|
||||||
from langchain_openai.embeddings.base import OpenAIEmbeddings
|
from langchain_openai.embeddings.base import OpenAIEmbeddings
|
||||||
from pydantic.v1.types import SecretStr
|
|
||||||
|
|
||||||
from langflow.field_typing import NestedDict
|
from langflow.field_typing import NestedDict
|
||||||
from langflow.interface.custom.custom_component import CustomComponent
|
from langflow.interface.custom.custom_component import CustomComponent
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Any, List, Optional
|
from typing import Any, List, Optional, Text
|
||||||
|
|
||||||
from langchain_core.tools import StructuredTool
|
from langchain_core.tools import StructuredTool
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
@ -8,7 +8,6 @@ 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 build_function_and_schema
|
from langflow.helpers.flow import build_function_and_schema
|
||||||
from langflow.schema.dotdict import dotdict
|
from langflow.schema.dotdict import dotdict
|
||||||
from langflow.schema.schema import Record
|
|
||||||
|
|
||||||
|
|
||||||
class FlowToolComponent(CustomComponent):
|
class FlowToolComponent(CustomComponent):
|
||||||
|
|
@ -20,7 +19,7 @@ class FlowToolComponent(CustomComponent):
|
||||||
flow_records = self.list_flows()
|
flow_records = self.list_flows()
|
||||||
return [flow_record.data["name"] for flow_record in flow_records]
|
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.
|
Retrieves a flow by its name.
|
||||||
|
|
||||||
|
|
@ -83,4 +82,4 @@ class FlowToolComponent(CustomComponent):
|
||||||
description_repr = repr(tool.description).strip("'")
|
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()])
|
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}"
|
self.status = f"{description_repr}\nArguments:\n{args_str}"
|
||||||
return tool # type: ignore
|
return tool
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
from typing import Any, List, Optional, Tuple
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from langflow.custom import CustomComponent
|
from langflow.custom import CustomComponent
|
||||||
from langflow.graph.graph.base import Graph
|
from langflow.graph.graph.base import Graph
|
||||||
from langflow.graph.schema import ResultData, RunOutputs
|
from langflow.graph.schema import ResultData, RunOutputs
|
||||||
|
from langflow.graph.vertex.base import Vertex
|
||||||
from langflow.schema import Record
|
from langflow.schema import Record
|
||||||
from langflow.schema.dotdict import dotdict
|
from langflow.schema.dotdict import dotdict
|
||||||
from langflow.template.field.base import TemplateField
|
from langflow.template.field.base import TemplateField
|
||||||
|
|
@ -50,7 +51,7 @@ class SubFlowComponent(CustomComponent):
|
||||||
|
|
||||||
return build_config
|
return build_config
|
||||||
|
|
||||||
def get_flow_inputs(self, graph: Graph) -> List[Record]:
|
def get_flow_inputs(self, graph: Graph) -> List[Vertex]:
|
||||||
inputs = []
|
inputs = []
|
||||||
for vertex in graph.vertices:
|
for vertex in graph.vertices:
|
||||||
if vertex.is_input:
|
if vertex.is_input:
|
||||||
|
|
@ -58,13 +59,13 @@ class SubFlowComponent(CustomComponent):
|
||||||
logger.debug(inputs)
|
logger.debug(inputs)
|
||||||
return 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] = []
|
new_fields: list[TemplateField] = []
|
||||||
for input_id, input_display_name, input_description in inputs:
|
for vertex in inputs:
|
||||||
field = TemplateField(
|
field = TemplateField(
|
||||||
display_name=input_display_name,
|
display_name=vertex.display_name,
|
||||||
name=input_id,
|
name=vertex.id,
|
||||||
info=input_description,
|
info=vertex.description,
|
||||||
field_type="str",
|
field_type="str",
|
||||||
default=None,
|
default=None,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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.constants import ALL_TOOLS_NAMES, CUSTOM_TOOLS, FILE_TOOLS, OTHER_TOOLS
|
||||||
from langflow.interface.tools.util import get_tool_params
|
from langflow.interface.tools.util import get_tool_params
|
||||||
from langflow.legacy_custom import customs
|
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.services.deps import get_settings_service
|
||||||
from langflow.template.field.base import TemplateField
|
from langflow.template.field.base import TemplateField
|
||||||
from langflow.template.template.base import Template
|
from langflow.template.template.base import Template
|
||||||
|
|
|
||||||
|
|
@ -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")
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue