* Add `required_inputs` field to `Output` model in `base.py` * Refactor ComponentTool to ComponentToolkit and enhance tool creation logic - Replaced `ComponentTool` with `ComponentToolkit` to better encapsulate component-related tools. - Introduced `build_description` and `_build_output_function` helper functions for dynamic tool creation. - Updated tool initialization to handle multiple outputs and required inputs using `StructuredTool`. - Improved schema creation for tool arguments based on component inputs. * Refactor `to_tool` method to `to_toolkit` to use `ComponentToolkit` instead of `ComponentTool` * Refactor `ComponentTool` to `ComponentToolkit` in unit tests - Updated import statements to reflect the new `ComponentToolkit` class. - Modified test logic to use `ComponentToolkit` for retrieving tools. - Adjusted assertions to match the new structure and output format. - Ensured compatibility with `Message` schema for output validation. * Refactor `test_component_to_tool` to validate `ComponentToolkit` and tool properties * Refactor `build_description` to include input types in the output format * Add method to set required inputs for outputs based on method analysis - Introduced `_set_output_required_inputs` method to determine and set required inputs for each output by analyzing the method's source code. - Added necessary imports (`ast` and `dedent`) to support the new functionality. * Update test to assert full tool description in test_component_to_tool.py * Add unit tests for verifying required inputs of various components - Added tests to ensure that required inputs for outputs are present in the inputs of `ChatInput`, `ChatOutput`, `SequentialTaskComponent`, `ToolCallingAgentComponent`, and `OpenAIModelComponent`. - Included helper functions to check if required inputs are in inputs and to assert that all outputs have different required inputs. * Add RequiredInputsVisitor to identify required inputs in AST nodes - Introduced RequiredInputsVisitor class to traverse AST nodes and collect required inputs. - The visitor checks for 'self' attributes matching the provided inputs and adds them to the required_inputs set. * Refactor required inputs extraction using `RequiredInputsVisitor` * Add feature flags configuration for toolkit output in settings * Add toolkit output handling based on feature flag in custom component utils * Add method to append 'component_as_tool' output in custom component * Add unit test for toolkit output feature flag in custom component * Add utility functions for lazy loading and instantiating input types in langflow - Introduced `get_InputTypesMap` for lazy loading of `InputTypesMap`. - Added `instantiate_input` function to create instances of input types dynamically. - Included type checking and error handling for invalid input types. * Refactor input instantiation logic and update imports - Removed `instantiate_input` function from `inputs.py` and moved it to `utils.py`. - Updated imports in `base.py` to reflect the new location of `instantiate_input`. - Added missing import for `Callable` in `base.py`. * Refactor import statement to use `instantiate_input` from `langflow.inputs.utils` in test_inputs.py * Add TOOL_OUTPUT_NAME constant to tools module * Add type checking and TOOL_OUTPUT_NAME filter in ComponentToolkit - Introduced `TYPE_CHECKING` for type hints to avoid circular imports. - Added `TOOL_OUTPUT_NAME` constant to filter specific outputs in `ComponentToolkit`. - Updated type annotations to use forward references. * Refactor component toolkit import to avoid circular dependency and use constant for tool output name * Refactor `ComponentToolkit` class to remove inheritance from `BaseToolkit` and add an initializer for `component` * Add unit test for ComponentToolkit in test_component_to_tool - Added `test_component_to_tool_has_no_component_as_tool` to verify that `ComponentToolkit` correctly initializes with a `ChatInput` component and returns the expected tools. * Refactor toolkit output handling to `custom_component` module * fix: mypy errors union-attr and arg-type * Add 'OTHER' field type to schema in langflow/io/schema.py * Add tool name formatting to ComponentToolkit to ensure valid characters * Refactor toolkit output handling and add type hint for `to_toolkit` method * Add `is_interface_component` attribute to vertex types and update import order * Add tests for ToolCallingAgentComponent and ChatOutput with API key handling - Updated `test_component_tool` to reflect new description format. - Added `test_component_tool_with_api_key` to test `ToolCallingAgentComponent` with `ChatOutput` and OpenAI API key. - Enabled `add_toolkit_output` feature flag for testing. * Refactor `_find_matching_output_method` to accept `input_name` parameter for more precise input-output matching * Replace ValueError with warning in build_description function * use chat_output component directly in set * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 3/3) * Refactor: Reorder method calls in `__init__` for logical consistency Moved `set_class_code` method call to ensure output types and required inputs are set before class code initialization. * Update _format_tool_name to allow '.' in tool names * Refactor `_format_tool_name` to remove non-alphanumeric characters * Update test assertions for component tool name and output mapping * Handle case where 'required_inputs' is empty in 'component_tool.py' * Refactor import statements for better readability in `base.py` * [autofix.ci] apply automated fixes * Add noqa comment to suppress import warning and re-add Any import in base.py --------- Co-authored-by: italojohnny <italojohnnydosanjos@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1467 lines
No EOL
68 KiB
JSON
1467 lines
No EOL
68 KiB
JSON
{
|
|
"data": {
|
|
"edges": [
|
|
{
|
|
"className": "",
|
|
"data": {
|
|
"sourceHandle": {
|
|
"dataType": "ToolCallingAgent",
|
|
"id": "ToolCallingAgent-mf0BN",
|
|
"name": "response",
|
|
"output_types": [
|
|
"Message"
|
|
]
|
|
},
|
|
"targetHandle": {
|
|
"fieldName": "input_value",
|
|
"id": "ChatOutput-Ag9YG",
|
|
"inputTypes": [
|
|
"Message"
|
|
],
|
|
"type": "str"
|
|
}
|
|
},
|
|
"id": "reactflow__edge-ToolCallingAgent-mf0BN{œdataTypeœ:œToolCallingAgentœ,œidœ:œToolCallingAgent-mf0BNœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-Ag9YG{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-Ag9YGœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
|
|
"source": "ToolCallingAgent-mf0BN",
|
|
"sourceHandle": "{œdataTypeœ: œToolCallingAgentœ, œidœ: œToolCallingAgent-mf0BNœ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}",
|
|
"target": "ChatOutput-Ag9YG",
|
|
"targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-Ag9YGœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
|
|
},
|
|
{
|
|
"className": "",
|
|
"data": {
|
|
"sourceHandle": {
|
|
"dataType": "OpenAIModel",
|
|
"id": "OpenAIModel-1ioeW",
|
|
"name": "model_output",
|
|
"output_types": [
|
|
"LanguageModel"
|
|
]
|
|
},
|
|
"targetHandle": {
|
|
"fieldName": "llm",
|
|
"id": "ToolCallingAgent-mf0BN",
|
|
"inputTypes": [
|
|
"LanguageModel"
|
|
],
|
|
"type": "other"
|
|
}
|
|
},
|
|
"id": "reactflow__edge-OpenAIModel-1ioeW{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-1ioeWœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-ToolCallingAgent-mf0BN{œfieldNameœ:œllmœ,œidœ:œToolCallingAgent-mf0BNœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}",
|
|
"source": "OpenAIModel-1ioeW",
|
|
"sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-1ioeWœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}",
|
|
"target": "ToolCallingAgent-mf0BN",
|
|
"targetHandle": "{œfieldNameœ: œllmœ, œidœ: œToolCallingAgent-mf0BNœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}"
|
|
},
|
|
{
|
|
"className": "",
|
|
"data": {
|
|
"sourceHandle": {
|
|
"dataType": "CalculatorTool",
|
|
"id": "CalculatorTool-Nb4P5",
|
|
"name": "api_build_tool",
|
|
"output_types": [
|
|
"Tool"
|
|
]
|
|
},
|
|
"targetHandle": {
|
|
"fieldName": "tools",
|
|
"id": "ToolCallingAgent-mf0BN",
|
|
"inputTypes": [
|
|
"Tool",
|
|
"BaseTool"
|
|
],
|
|
"type": "other"
|
|
}
|
|
},
|
|
"id": "reactflow__edge-CalculatorTool-Nb4P5{œdataTypeœ:œCalculatorToolœ,œidœ:œCalculatorTool-Nb4P5œ,œnameœ:œapi_build_toolœ,œoutput_typesœ:[œToolœ]}-ToolCallingAgent-mf0BN{œfieldNameœ:œtoolsœ,œidœ:œToolCallingAgent-mf0BNœ,œinputTypesœ:[œToolœ,œBaseToolœ],œtypeœ:œotherœ}",
|
|
"source": "CalculatorTool-Nb4P5",
|
|
"sourceHandle": "{œdataTypeœ: œCalculatorToolœ, œidœ: œCalculatorTool-Nb4P5œ, œnameœ: œapi_build_toolœ, œoutput_typesœ: [œToolœ]}",
|
|
"target": "ToolCallingAgent-mf0BN",
|
|
"targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œToolCallingAgent-mf0BNœ, œinputTypesœ: [œToolœ, œBaseToolœ], œtypeœ: œotherœ}"
|
|
},
|
|
{
|
|
"className": "",
|
|
"data": {
|
|
"sourceHandle": {
|
|
"dataType": "ChatInput",
|
|
"id": "ChatInput-X3ARP",
|
|
"name": "message",
|
|
"output_types": [
|
|
"Message"
|
|
]
|
|
},
|
|
"targetHandle": {
|
|
"fieldName": "input_value",
|
|
"id": "ToolCallingAgent-mf0BN",
|
|
"inputTypes": [
|
|
"Message"
|
|
],
|
|
"type": "str"
|
|
}
|
|
},
|
|
"id": "reactflow__edge-ChatInput-X3ARP{œdataTypeœ:œChatInputœ,œidœ:œChatInput-X3ARPœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-ToolCallingAgent-mf0BN{œfieldNameœ:œinput_valueœ,œidœ:œToolCallingAgent-mf0BNœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
|
|
"source": "ChatInput-X3ARP",
|
|
"sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-X3ARPœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}",
|
|
"target": "ToolCallingAgent-mf0BN",
|
|
"targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œToolCallingAgent-mf0BNœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
|
|
},
|
|
{
|
|
"data": {
|
|
"sourceHandle": {
|
|
"dataType": "PythonREPLTool",
|
|
"id": "PythonREPLTool-i922a",
|
|
"name": "api_build_tool",
|
|
"output_types": [
|
|
"Tool"
|
|
]
|
|
},
|
|
"targetHandle": {
|
|
"fieldName": "tools",
|
|
"id": "ToolCallingAgent-mf0BN",
|
|
"inputTypes": [
|
|
"Tool",
|
|
"BaseTool"
|
|
],
|
|
"type": "other"
|
|
}
|
|
},
|
|
"id": "reactflow__edge-PythonREPLTool-i922a{œdataTypeœ:œPythonREPLToolœ,œidœ:œPythonREPLTool-i922aœ,œnameœ:œapi_build_toolœ,œoutput_typesœ:[œToolœ]}-ToolCallingAgent-mf0BN{œfieldNameœ:œtoolsœ,œidœ:œToolCallingAgent-mf0BNœ,œinputTypesœ:[œToolœ,œBaseToolœ],œtypeœ:œotherœ}",
|
|
"source": "PythonREPLTool-i922a",
|
|
"sourceHandle": "{œdataTypeœ: œPythonREPLToolœ, œidœ: œPythonREPLTool-i922aœ, œnameœ: œapi_build_toolœ, œoutput_typesœ: [œToolœ]}",
|
|
"target": "ToolCallingAgent-mf0BN",
|
|
"targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œToolCallingAgent-mf0BNœ, œinputTypesœ: [œToolœ, œBaseToolœ], œtypeœ: œotherœ}"
|
|
}
|
|
],
|
|
"nodes": [
|
|
{
|
|
"data": {
|
|
"id": "ChatInput-X3ARP",
|
|
"node": {
|
|
"base_classes": [
|
|
"Message"
|
|
],
|
|
"beta": false,
|
|
"conditional_paths": [],
|
|
"custom_fields": {},
|
|
"description": "Get chat inputs from the Playground.",
|
|
"display_name": "Chat Input",
|
|
"documentation": "",
|
|
"edited": false,
|
|
"field_order": [
|
|
"input_value",
|
|
"should_store_message",
|
|
"sender",
|
|
"sender_name",
|
|
"session_id",
|
|
"files"
|
|
],
|
|
"frozen": false,
|
|
"icon": "ChatInput",
|
|
"lf_version": "1.0.16",
|
|
"metadata": {},
|
|
"output_types": [],
|
|
"outputs": [
|
|
{
|
|
"cache": true,
|
|
"display_name": "Message",
|
|
"method": "message_response",
|
|
"name": "message",
|
|
"selected": "Message",
|
|
"types": [
|
|
"Message"
|
|
],
|
|
"value": "__UNDEFINED__"
|
|
}
|
|
],
|
|
"pinned": false,
|
|
"template": {
|
|
"_type": "Component",
|
|
"code": {
|
|
"advanced": true,
|
|
"dynamic": true,
|
|
"fileTypes": [],
|
|
"file_path": "",
|
|
"info": "",
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"multiline": true,
|
|
"name": "code",
|
|
"password": false,
|
|
"placeholder": "",
|
|
"required": true,
|
|
"show": true,
|
|
"title_case": false,
|
|
"type": "code",
|
|
"value": "from langflow.base.data.utils import IMG_FILE_TYPES, TEXT_FILE_TYPES\nfrom langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput\nfrom langflow.io import DropdownInput, FileInput, MessageTextInput, MultilineInput, Output\nfrom langflow.memory import store_message\nfrom langflow.schema.message import Message\nfrom langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_NAME_USER, MESSAGE_SENDER_USER\n\n\nclass ChatInput(ChatComponent):\n display_name = \"Chat Input\"\n description = \"Get chat inputs from the Playground.\"\n icon = \"ChatInput\"\n name = \"ChatInput\"\n\n inputs = [\n MultilineInput(\n name=\"input_value\",\n display_name=\"Text\",\n value=\"\",\n info=\"Message to be passed as input.\",\n ),\n BoolInput(\n name=\"should_store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],\n value=MESSAGE_SENDER_USER,\n info=\"Type of sender.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=MESSAGE_SENDER_NAME_USER,\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\",\n display_name=\"Session ID\",\n info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n advanced=True,\n ),\n FileInput(\n name=\"files\",\n display_name=\"Files\",\n file_types=TEXT_FILE_TYPES + IMG_FILE_TYPES,\n info=\"Files to be sent with the message.\",\n advanced=True,\n is_list=True,\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n files=self.files,\n )\n\n if (\n self.session_id\n and isinstance(message, Message)\n and isinstance(message.text, str)\n and self.should_store_message\n ):\n store_message(\n message,\n flow_id=self.graph.flow_id,\n )\n self.message.value = message\n\n self.status = message\n return message\n"
|
|
},
|
|
"files": {
|
|
"_input_type": "FileInput",
|
|
"advanced": true,
|
|
"display_name": "Files",
|
|
"dynamic": false,
|
|
"fileTypes": [
|
|
"txt",
|
|
"md",
|
|
"mdx",
|
|
"csv",
|
|
"json",
|
|
"yaml",
|
|
"yml",
|
|
"xml",
|
|
"html",
|
|
"htm",
|
|
"pdf",
|
|
"docx",
|
|
"py",
|
|
"sh",
|
|
"sql",
|
|
"js",
|
|
"ts",
|
|
"tsx",
|
|
"jpg",
|
|
"jpeg",
|
|
"png",
|
|
"bmp",
|
|
"image"
|
|
],
|
|
"file_path": "",
|
|
"info": "Files to be sent with the message.",
|
|
"list": true,
|
|
"name": "files",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "file",
|
|
"value": ""
|
|
},
|
|
"input_value": {
|
|
"_input_type": "MultilineInput",
|
|
"advanced": false,
|
|
"display_name": "Text",
|
|
"dynamic": false,
|
|
"info": "Message to be passed as input.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"multiline": true,
|
|
"name": "input_value",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "Write a short python script to calculate 4+4, run it and display the result by printing it."
|
|
},
|
|
"sender": {
|
|
"_input_type": "DropdownInput",
|
|
"advanced": true,
|
|
"combobox": false,
|
|
"display_name": "Sender Type",
|
|
"dynamic": false,
|
|
"info": "Type of sender.",
|
|
"name": "sender",
|
|
"options": [
|
|
"Machine",
|
|
"User"
|
|
],
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "User"
|
|
},
|
|
"sender_name": {
|
|
"_input_type": "MessageTextInput",
|
|
"advanced": true,
|
|
"display_name": "Sender Name",
|
|
"dynamic": false,
|
|
"info": "Name of the sender.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "sender_name",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "User"
|
|
},
|
|
"session_id": {
|
|
"_input_type": "MessageTextInput",
|
|
"advanced": true,
|
|
"display_name": "Session ID",
|
|
"dynamic": false,
|
|
"info": "The session ID of the chat. If empty, the current session ID parameter will be used.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "session_id",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": ""
|
|
},
|
|
"should_store_message": {
|
|
"_input_type": "BoolInput",
|
|
"advanced": true,
|
|
"display_name": "Store Messages",
|
|
"dynamic": false,
|
|
"info": "Store the message in the history.",
|
|
"list": false,
|
|
"name": "should_store_message",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "bool",
|
|
"value": true
|
|
}
|
|
}
|
|
},
|
|
"type": "ChatInput"
|
|
},
|
|
"dragging": false,
|
|
"height": 302,
|
|
"id": "ChatInput-X3ARP",
|
|
"position": {
|
|
"x": 1760.192972923414,
|
|
"y": -191.51901724049213
|
|
},
|
|
"positionAbsolute": {
|
|
"x": 1760.192972923414,
|
|
"y": -191.51901724049213
|
|
},
|
|
"selected": false,
|
|
"type": "genericNode",
|
|
"width": 384
|
|
},
|
|
{
|
|
"data": {
|
|
"id": "ChatOutput-Ag9YG",
|
|
"node": {
|
|
"base_classes": [
|
|
"Message"
|
|
],
|
|
"beta": false,
|
|
"conditional_paths": [],
|
|
"custom_fields": {},
|
|
"description": "Display a chat message in the Playground.",
|
|
"display_name": "Chat Output",
|
|
"documentation": "",
|
|
"edited": false,
|
|
"field_order": [
|
|
"input_value",
|
|
"should_store_message",
|
|
"sender",
|
|
"sender_name",
|
|
"session_id",
|
|
"data_template"
|
|
],
|
|
"frozen": false,
|
|
"icon": "ChatOutput",
|
|
"lf_version": "1.0.16",
|
|
"metadata": {},
|
|
"output_types": [],
|
|
"outputs": [
|
|
{
|
|
"cache": true,
|
|
"display_name": "Message",
|
|
"method": "message_response",
|
|
"name": "message",
|
|
"selected": "Message",
|
|
"types": [
|
|
"Message"
|
|
],
|
|
"value": "__UNDEFINED__"
|
|
}
|
|
],
|
|
"pinned": false,
|
|
"template": {
|
|
"_type": "Component",
|
|
"code": {
|
|
"advanced": true,
|
|
"dynamic": true,
|
|
"fileTypes": [],
|
|
"file_path": "",
|
|
"info": "",
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"multiline": true,
|
|
"name": "code",
|
|
"password": false,
|
|
"placeholder": "",
|
|
"required": true,
|
|
"show": true,
|
|
"title_case": false,
|
|
"type": "code",
|
|
"value": "from langflow.base.io.chat import ChatComponent\nfrom langflow.inputs import BoolInput\nfrom langflow.io import DropdownInput, MessageTextInput, Output\nfrom langflow.memory import store_message\nfrom langflow.schema.message import Message\nfrom langflow.utils.constants import MESSAGE_SENDER_AI, MESSAGE_SENDER_NAME_AI, MESSAGE_SENDER_USER\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n icon = \"ChatOutput\"\n name = \"ChatOutput\"\n\n inputs = [\n MessageTextInput(\n name=\"input_value\",\n display_name=\"Text\",\n info=\"Message to be passed as output.\",\n ),\n BoolInput(\n name=\"should_store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],\n value=MESSAGE_SENDER_AI,\n advanced=True,\n info=\"Type of sender.\",\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=MESSAGE_SENDER_NAME_AI,\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\",\n display_name=\"Session ID\",\n info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n ]\n outputs = [\n Output(display_name=\"Message\", name=\"message\", method=\"message_response\"),\n ]\n\n def message_response(self) -> Message:\n message = Message(\n text=self.input_value,\n sender=self.sender,\n sender_name=self.sender_name,\n session_id=self.session_id,\n )\n if (\n self.session_id\n and isinstance(message, Message)\n and isinstance(message.text, str)\n and self.should_store_message\n ):\n store_message(\n message,\n flow_id=self.graph.flow_id,\n )\n self.message.value = message\n\n self.status = message\n return message\n"
|
|
},
|
|
"data_template": {
|
|
"_input_type": "MessageTextInput",
|
|
"advanced": true,
|
|
"display_name": "Data Template",
|
|
"dynamic": false,
|
|
"info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "data_template",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "{text}"
|
|
},
|
|
"input_value": {
|
|
"_input_type": "MessageTextInput",
|
|
"advanced": false,
|
|
"display_name": "Text",
|
|
"dynamic": false,
|
|
"info": "Message to be passed as output.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "input_value",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": ""
|
|
},
|
|
"sender": {
|
|
"_input_type": "DropdownInput",
|
|
"advanced": true,
|
|
"combobox": false,
|
|
"display_name": "Sender Type",
|
|
"dynamic": false,
|
|
"info": "Type of sender.",
|
|
"name": "sender",
|
|
"options": [
|
|
"Machine",
|
|
"User"
|
|
],
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "Machine"
|
|
},
|
|
"sender_name": {
|
|
"_input_type": "MessageTextInput",
|
|
"advanced": true,
|
|
"display_name": "Sender Name",
|
|
"dynamic": false,
|
|
"info": "Name of the sender.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "sender_name",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "AI"
|
|
},
|
|
"session_id": {
|
|
"_input_type": "MessageTextInput",
|
|
"advanced": true,
|
|
"display_name": "Session ID",
|
|
"dynamic": false,
|
|
"info": "The session ID of the chat. If empty, the current session ID parameter will be used.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "session_id",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": ""
|
|
},
|
|
"should_store_message": {
|
|
"_input_type": "BoolInput",
|
|
"advanced": true,
|
|
"display_name": "Store Messages",
|
|
"dynamic": false,
|
|
"info": "Store the message in the history.",
|
|
"list": false,
|
|
"name": "should_store_message",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "bool",
|
|
"value": true
|
|
}
|
|
}
|
|
},
|
|
"type": "ChatOutput"
|
|
},
|
|
"dragging": false,
|
|
"height": 302,
|
|
"id": "ChatOutput-Ag9YG",
|
|
"position": {
|
|
"x": 3968.8870036313238,
|
|
"y": 627.770746142633
|
|
},
|
|
"positionAbsolute": {
|
|
"x": 3968.8870036313238,
|
|
"y": 627.770746142633
|
|
},
|
|
"selected": false,
|
|
"type": "genericNode",
|
|
"width": 384
|
|
},
|
|
{
|
|
"data": {
|
|
"description": "Generates text using OpenAI LLMs.",
|
|
"display_name": "OpenAI",
|
|
"id": "OpenAIModel-1ioeW",
|
|
"node": {
|
|
"base_classes": [
|
|
"LanguageModel",
|
|
"Message"
|
|
],
|
|
"beta": false,
|
|
"conditional_paths": [],
|
|
"custom_fields": {},
|
|
"description": "Generates text using OpenAI LLMs.",
|
|
"display_name": "OpenAI",
|
|
"documentation": "",
|
|
"edited": false,
|
|
"field_order": [
|
|
"input_value",
|
|
"system_message",
|
|
"stream",
|
|
"max_tokens",
|
|
"model_kwargs",
|
|
"json_mode",
|
|
"output_schema",
|
|
"model_name",
|
|
"openai_api_base",
|
|
"api_key",
|
|
"temperature",
|
|
"seed"
|
|
],
|
|
"frozen": false,
|
|
"icon": "OpenAI",
|
|
"lf_version": "1.0.16",
|
|
"metadata": {},
|
|
"output_types": [],
|
|
"outputs": [
|
|
{
|
|
"cache": true,
|
|
"display_name": "Text",
|
|
"method": "text_response",
|
|
"name": "text_output",
|
|
"required_inputs": [
|
|
"input_value",
|
|
"stream",
|
|
"system_message"
|
|
],
|
|
"selected": "Message",
|
|
"types": [
|
|
"Message"
|
|
],
|
|
"value": "__UNDEFINED__"
|
|
},
|
|
{
|
|
"cache": true,
|
|
"display_name": "Language Model",
|
|
"method": "build_model",
|
|
"name": "model_output",
|
|
"required_inputs": [
|
|
"api_key",
|
|
"json_mode",
|
|
"max_tokens",
|
|
"model_kwargs",
|
|
"model_name",
|
|
"openai_api_base",
|
|
"output_schema",
|
|
"seed",
|
|
"temperature"
|
|
],
|
|
"selected": "LanguageModel",
|
|
"types": [
|
|
"LanguageModel"
|
|
],
|
|
"value": "__UNDEFINED__"
|
|
}
|
|
],
|
|
"pinned": false,
|
|
"template": {
|
|
"_type": "Component",
|
|
"api_key": {
|
|
"_input_type": "SecretStrInput",
|
|
"advanced": false,
|
|
"display_name": "OpenAI API Key",
|
|
"dynamic": false,
|
|
"info": "The OpenAI API Key to use for the OpenAI model.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"load_from_db": true,
|
|
"name": "api_key",
|
|
"password": true,
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"type": "str",
|
|
"value": "OPENAI_API_KEY"
|
|
},
|
|
"code": {
|
|
"advanced": true,
|
|
"dynamic": true,
|
|
"fileTypes": [],
|
|
"file_path": "",
|
|
"info": "",
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"multiline": true,
|
|
"name": "code",
|
|
"password": false,
|
|
"placeholder": "",
|
|
"required": true,
|
|
"show": true,
|
|
"title_case": false,
|
|
"type": "code",
|
|
"value": "import operator\nfrom functools import reduce\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import OPENAI_MODEL_NAMES\nfrom langflow.field_typing import LanguageModel\nfrom langflow.field_typing.range_spec import RangeSpec\nfrom langflow.inputs import (\n BoolInput,\n DictInput,\n DropdownInput,\n FloatInput,\n IntInput,\n SecretStrInput,\n StrInput,\n)\nfrom langflow.inputs.inputs import HandleInput\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n name = \"OpenAIModel\"\n\n inputs = LCModelComponent._base_inputs + [\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n range_spec=RangeSpec(min=0, max=128000),\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n advanced=True,\n info=\"If True, it will output JSON regardless of passing a schema.\",\n ),\n DictInput(\n name=\"output_schema\",\n is_list=True,\n display_name=\"Schema\",\n advanced=True,\n info=\"The schema for the Output of the model. \"\n \"You must pass the word JSON in the prompt. \"\n \"If left blank, JSON mode will be disabled.\",\n ),\n DropdownInput(\n name=\"model_name\",\n display_name=\"Model Name\",\n advanced=False,\n options=OPENAI_MODEL_NAMES,\n value=OPENAI_MODEL_NAMES[0],\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. \"\n \"Defaults to https://api.openai.com/v1. \"\n \"You can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\n ),\n HandleInput(\n name=\"output_parser\",\n display_name=\"Output Parser\",\n info=\"The parser to use to parse the output of the model\",\n advanced=True,\n input_types=[\"OutputParser\"],\n ),\n ]\n\n def build_model(self) -> LanguageModel: # type: ignore[type-var]\n # self.output_schema is a list of dictionaries\n # let's convert it to a dictionary\n output_schema_dict: dict[str, str] = reduce(operator.ior, self.output_schema or {}, {})\n openai_api_key = self.api_key\n temperature = self.temperature\n model_name: str = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs or {}\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n json_mode = bool(output_schema_dict) or self.json_mode\n seed = self.seed\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature if temperature is not None else 0.1,\n seed=seed,\n )\n if json_mode:\n if output_schema_dict:\n output = output.with_structured_output(schema=output_schema_dict, method=\"json_mode\") # type: ignore\n else:\n output = output.bind(response_format={\"type\": \"json_object\"}) # type: ignore\n\n return output # type: ignore\n\n def _get_exception_message(self, e: Exception):\n \"\"\"\n Get a message from an OpenAI exception.\n\n Args:\n exception (Exception): The exception to get the message from.\n\n Returns:\n str: The message from the exception.\n \"\"\"\n\n try:\n from openai import BadRequestError\n except ImportError:\n return None\n if isinstance(e, BadRequestError):\n message = e.body.get(\"message\") # type: ignore\n if message:\n return message\n return None\n"
|
|
},
|
|
"input_value": {
|
|
"_input_type": "MessageInput",
|
|
"advanced": false,
|
|
"display_name": "Input",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "input_value",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": ""
|
|
},
|
|
"json_mode": {
|
|
"_input_type": "BoolInput",
|
|
"advanced": true,
|
|
"display_name": "JSON Mode",
|
|
"dynamic": false,
|
|
"info": "If True, it will output JSON regardless of passing a schema.",
|
|
"list": false,
|
|
"name": "json_mode",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "bool",
|
|
"value": false
|
|
},
|
|
"max_tokens": {
|
|
"_input_type": "IntInput",
|
|
"advanced": true,
|
|
"display_name": "Max Tokens",
|
|
"dynamic": false,
|
|
"info": "The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
|
|
"list": false,
|
|
"name": "max_tokens",
|
|
"placeholder": "",
|
|
"range_spec": {
|
|
"max": 128000,
|
|
"min": 0,
|
|
"step": 0.1,
|
|
"step_type": "float"
|
|
},
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "int",
|
|
"value": ""
|
|
},
|
|
"model_kwargs": {
|
|
"_input_type": "DictInput",
|
|
"advanced": true,
|
|
"display_name": "Model Kwargs",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"list": false,
|
|
"name": "model_kwargs",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"type": "dict",
|
|
"value": {}
|
|
},
|
|
"model_name": {
|
|
"_input_type": "DropdownInput",
|
|
"advanced": false,
|
|
"combobox": false,
|
|
"display_name": "Model Name",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"load_from_db": false,
|
|
"name": "model_name",
|
|
"options": [
|
|
"gpt-4o-mini",
|
|
"gpt-4o",
|
|
"gpt-4-turbo",
|
|
"gpt-4-turbo-preview",
|
|
"gpt-4",
|
|
"gpt-3.5-turbo",
|
|
"gpt-3.5-turbo-0125"
|
|
],
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "gpt-4o-mini"
|
|
},
|
|
"openai_api_base": {
|
|
"_input_type": "StrInput",
|
|
"advanced": true,
|
|
"display_name": "OpenAI API Base",
|
|
"dynamic": false,
|
|
"info": "The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.",
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "openai_api_base",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": ""
|
|
},
|
|
"output_parser": {
|
|
"_input_type": "HandleInput",
|
|
"advanced": true,
|
|
"display_name": "Output Parser",
|
|
"dynamic": false,
|
|
"info": "The parser to use to parse the output of the model",
|
|
"input_types": [
|
|
"OutputParser"
|
|
],
|
|
"list": false,
|
|
"name": "output_parser",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "other",
|
|
"value": ""
|
|
},
|
|
"output_schema": {
|
|
"_input_type": "DictInput",
|
|
"advanced": true,
|
|
"display_name": "Schema",
|
|
"dynamic": false,
|
|
"info": "The schema for the Output of the model. You must pass the word JSON in the prompt. If left blank, JSON mode will be disabled.",
|
|
"list": true,
|
|
"name": "output_schema",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"type": "dict",
|
|
"value": {}
|
|
},
|
|
"seed": {
|
|
"_input_type": "IntInput",
|
|
"advanced": true,
|
|
"display_name": "Seed",
|
|
"dynamic": false,
|
|
"info": "The seed controls the reproducibility of the job.",
|
|
"list": false,
|
|
"name": "seed",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "int",
|
|
"value": 1
|
|
},
|
|
"stream": {
|
|
"_input_type": "BoolInput",
|
|
"advanced": true,
|
|
"display_name": "Stream",
|
|
"dynamic": false,
|
|
"info": "Stream the response from the model. Streaming works only in Chat.",
|
|
"list": false,
|
|
"name": "stream",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "bool",
|
|
"value": false
|
|
},
|
|
"system_message": {
|
|
"_input_type": "MessageTextInput",
|
|
"advanced": true,
|
|
"display_name": "System Message",
|
|
"dynamic": false,
|
|
"info": "System message to pass to the model.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "system_message",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": ""
|
|
},
|
|
"temperature": {
|
|
"_input_type": "FloatInput",
|
|
"advanced": false,
|
|
"display_name": "Temperature",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"list": false,
|
|
"name": "temperature",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "float",
|
|
"value": 0.1
|
|
}
|
|
}
|
|
},
|
|
"type": "OpenAIModel"
|
|
},
|
|
"dragging": false,
|
|
"height": 605,
|
|
"id": "OpenAIModel-1ioeW",
|
|
"position": {
|
|
"x": 2538.9919009235173,
|
|
"y": 1206.8619086167491
|
|
},
|
|
"positionAbsolute": {
|
|
"x": 2538.9919009235173,
|
|
"y": 1206.8619086167491
|
|
},
|
|
"selected": false,
|
|
"type": "genericNode",
|
|
"width": 384
|
|
},
|
|
{
|
|
"data": {
|
|
"id": "ToolCallingAgent-mf0BN",
|
|
"node": {
|
|
"base_classes": [
|
|
"AgentExecutor",
|
|
"Message"
|
|
],
|
|
"beta": true,
|
|
"conditional_paths": [],
|
|
"custom_fields": {},
|
|
"description": "Agent that uses tools to perform the given task.",
|
|
"display_name": "Agent",
|
|
"documentation": "",
|
|
"edited": true,
|
|
"field_order": [
|
|
"input_value",
|
|
"handle_parsing_errors",
|
|
"verbose",
|
|
"max_iterations",
|
|
"tools",
|
|
"llm",
|
|
"system_prompt",
|
|
"user_prompt",
|
|
"chat_history"
|
|
],
|
|
"frozen": false,
|
|
"icon": "bot-message-square",
|
|
"lf_version": "1.0.16",
|
|
"output_types": [],
|
|
"outputs": [
|
|
{
|
|
"cache": true,
|
|
"display_name": "Agent",
|
|
"hidden": true,
|
|
"method": "build_agent",
|
|
"name": "agent",
|
|
"selected": "AgentExecutor",
|
|
"types": [
|
|
"AgentExecutor"
|
|
],
|
|
"value": "__UNDEFINED__"
|
|
},
|
|
{
|
|
"cache": true,
|
|
"display_name": "Response",
|
|
"method": "message_response",
|
|
"name": "response",
|
|
"selected": "Message",
|
|
"types": [
|
|
"Message"
|
|
],
|
|
"value": "__UNDEFINED__"
|
|
}
|
|
],
|
|
"pinned": false,
|
|
"template": {
|
|
"_type": "Component",
|
|
"chat_history": {
|
|
"_input_type": "DataInput",
|
|
"advanced": true,
|
|
"display_name": "Chat History",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"input_types": [
|
|
"Data"
|
|
],
|
|
"list": true,
|
|
"name": "chat_history",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "other",
|
|
"value": ""
|
|
},
|
|
"code": {
|
|
"advanced": true,
|
|
"dynamic": true,
|
|
"fileTypes": [],
|
|
"file_path": "",
|
|
"info": "",
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"multiline": true,
|
|
"name": "code",
|
|
"password": false,
|
|
"placeholder": "",
|
|
"required": true,
|
|
"show": true,
|
|
"title_case": false,
|
|
"type": "code",
|
|
"value": "from typing import Optional, List\n\nfrom langchain.agents import create_tool_calling_agent\nfrom langchain_core.prompts import ChatPromptTemplate, PromptTemplate, HumanMessagePromptTemplate\nfrom langflow.base.agents.agent import LCToolsAgentComponent\nfrom langflow.inputs import MultilineInput\nfrom langflow.inputs.inputs import HandleInput, DataInput\nfrom langflow.schema import Data\n\n\nclass ToolCallingAgentComponent(LCToolsAgentComponent):\n display_name: str = \"Tool Calling Agent\"\n description: str = \"Agent that uses tools\"\n icon = \"bot-message-square\"\n beta = True\n name = \"ToolCallingAgent\"\n\n inputs = LCToolsAgentComponent._base_inputs + [\n HandleInput(name=\"llm\", display_name=\"Language Model\", input_types=[\"LanguageModel\"], required=True),\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"System Prompt\",\n info=\"System prompt for the agent.\",\n value=\"You are a helpful assistant\",\n ),\n MultilineInput(\n name=\"user_prompt\", display_name=\"Prompt\", info=\"This prompt must contain 'input' key.\", value=\"{input}\"\n ),\n DataInput(name=\"chat_history\", display_name=\"Chat History\", is_list=True, advanced=True),\n ]\n\n def get_chat_history_data(self) -> Optional[List[Data]]:\n return self.chat_history\n\n def create_agent_runnable(self):\n if \"input\" not in self.user_prompt:\n raise ValueError(\"Prompt must contain 'input' key.\")\n messages = [\n (\"system\", self.system_prompt),\n (\"placeholder\", \"{chat_history}\"),\n HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=[\"input\"], template=self.user_prompt)),\n (\"placeholder\", \"{agent_scratchpad}\"),\n ]\n prompt = ChatPromptTemplate.from_messages(messages)\n return create_tool_calling_agent(self.llm, self.tools, prompt)\n"
|
|
},
|
|
"handle_parsing_errors": {
|
|
"_input_type": "BoolInput",
|
|
"advanced": true,
|
|
"display_name": "Handle Parse Errors",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"list": false,
|
|
"name": "handle_parsing_errors",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "bool",
|
|
"value": true
|
|
},
|
|
"input_value": {
|
|
"_input_type": "MessageTextInput",
|
|
"advanced": false,
|
|
"display_name": "Input",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "input_value",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": ""
|
|
},
|
|
"llm": {
|
|
"_input_type": "HandleInput",
|
|
"advanced": false,
|
|
"display_name": "Language Model",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"input_types": [
|
|
"LanguageModel"
|
|
],
|
|
"list": false,
|
|
"name": "llm",
|
|
"placeholder": "",
|
|
"required": true,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "other",
|
|
"value": ""
|
|
},
|
|
"max_iterations": {
|
|
"_input_type": "IntInput",
|
|
"advanced": true,
|
|
"display_name": "Max Iterations",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"list": false,
|
|
"name": "max_iterations",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "int",
|
|
"value": 15
|
|
},
|
|
"system_prompt": {
|
|
"_input_type": "MultilineInput",
|
|
"advanced": false,
|
|
"display_name": "System Prompt",
|
|
"dynamic": false,
|
|
"info": "System prompt for the agent.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"multiline": true,
|
|
"name": "system_prompt",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "You are an Amazing Agent that can use the tools provided to you and answer the question "
|
|
},
|
|
"tools": {
|
|
"_input_type": "HandleInput",
|
|
"advanced": false,
|
|
"display_name": "Tools",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"input_types": [
|
|
"Tool",
|
|
"BaseTool"
|
|
],
|
|
"list": true,
|
|
"load_from_db": false,
|
|
"name": "tools",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "other",
|
|
"value": ""
|
|
},
|
|
"user_prompt": {
|
|
"_input_type": "MultilineInput",
|
|
"advanced": false,
|
|
"display_name": "Prompt",
|
|
"dynamic": false,
|
|
"info": "This prompt must contain 'input' key.",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"multiline": true,
|
|
"name": "user_prompt",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "{input}"
|
|
},
|
|
"verbose": {
|
|
"_input_type": "BoolInput",
|
|
"advanced": true,
|
|
"display_name": "Verbose",
|
|
"dynamic": false,
|
|
"info": "",
|
|
"list": false,
|
|
"name": "verbose",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "bool",
|
|
"value": true
|
|
}
|
|
}
|
|
},
|
|
"type": "ToolCallingAgent"
|
|
},
|
|
"dragging": false,
|
|
"height": 598,
|
|
"id": "ToolCallingAgent-mf0BN",
|
|
"position": {
|
|
"x": 3276.3854573966964,
|
|
"y": 516.3304705434241
|
|
},
|
|
"positionAbsolute": {
|
|
"x": 3276.3854573966964,
|
|
"y": 516.3304705434241
|
|
},
|
|
"selected": false,
|
|
"type": "genericNode",
|
|
"width": 384
|
|
},
|
|
{
|
|
"data": {
|
|
"id": "CalculatorTool-Nb4P5",
|
|
"node": {
|
|
"base_classes": [
|
|
"Data",
|
|
"list",
|
|
"Sequence",
|
|
"Tool"
|
|
],
|
|
"beta": false,
|
|
"conditional_paths": [],
|
|
"custom_fields": {},
|
|
"description": "Perform basic arithmetic operations on a given expression.",
|
|
"display_name": "Calculator",
|
|
"documentation": "",
|
|
"edited": false,
|
|
"field_order": [
|
|
"expression"
|
|
],
|
|
"frozen": false,
|
|
"icon": "calculator",
|
|
"lf_version": "1.0.16",
|
|
"metadata": {},
|
|
"official": false,
|
|
"output_types": [],
|
|
"outputs": [
|
|
{
|
|
"cache": true,
|
|
"display_name": "Data",
|
|
"method": "run_model",
|
|
"name": "api_run_model",
|
|
"required_inputs": [
|
|
"expression"
|
|
],
|
|
"selected": "Data",
|
|
"types": [
|
|
"Data"
|
|
],
|
|
"value": "__UNDEFINED__"
|
|
},
|
|
{
|
|
"cache": true,
|
|
"display_name": "Tool",
|
|
"method": "build_tool",
|
|
"name": "api_build_tool",
|
|
"required_inputs": [
|
|
"expression"
|
|
],
|
|
"selected": "Tool",
|
|
"types": [
|
|
"Tool"
|
|
],
|
|
"value": "__UNDEFINED__"
|
|
}
|
|
],
|
|
"pinned": false,
|
|
"template": {
|
|
"_type": "Component",
|
|
"code": {
|
|
"advanced": true,
|
|
"dynamic": true,
|
|
"fileTypes": [],
|
|
"file_path": "",
|
|
"info": "",
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"multiline": true,
|
|
"name": "code",
|
|
"password": false,
|
|
"placeholder": "",
|
|
"required": true,
|
|
"show": true,
|
|
"title_case": false,
|
|
"type": "code",
|
|
"value": "import ast\nimport operator\n\nfrom langchain.tools import StructuredTool\nfrom pydantic import BaseModel, Field\n\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.field_typing import Tool\nfrom langflow.inputs import MessageTextInput\nfrom langflow.schema import Data\n\n\nclass CalculatorToolComponent(LCToolComponent):\n display_name = \"Calculator\"\n description = \"Perform basic arithmetic operations on a given expression.\"\n icon = \"calculator\"\n name = \"CalculatorTool\"\n\n inputs = [\n MessageTextInput(\n name=\"expression\",\n display_name=\"Expression\",\n info=\"The arithmetic expression to evaluate (e.g., '4*4*(33/22)+12-20').\",\n ),\n ]\n\n class CalculatorToolSchema(BaseModel):\n expression: str = Field(..., description=\"The arithmetic expression to evaluate.\")\n\n def run_model(self) -> list[Data]:\n return self._evaluate_expression(self.expression)\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"calculator\",\n description=\"Evaluate basic arithmetic expressions. Input should be a string containing the expression.\",\n func=self._evaluate_expression,\n args_schema=self.CalculatorToolSchema,\n )\n\n def _evaluate_expression(self, expression: str) -> list[Data]:\n try:\n # Define the allowed operators\n operators = {\n ast.Add: operator.add,\n ast.Sub: operator.sub,\n ast.Mult: operator.mul,\n ast.Div: operator.truediv,\n ast.Pow: operator.pow,\n }\n\n def eval_expr(node):\n if isinstance(node, ast.Num):\n return node.n\n if isinstance(node, ast.BinOp):\n return operators[type(node.op)](eval_expr(node.left), eval_expr(node.right))\n if isinstance(node, ast.UnaryOp):\n return operators[type(node.op)](eval_expr(node.operand))\n raise TypeError(node)\n\n # Parse the expression and evaluate it\n tree = ast.parse(expression, mode=\"eval\")\n result = eval_expr(tree.body)\n\n # Format the result to a reasonable number of decimal places\n formatted_result = f\"{result:.6f}\".rstrip(\"0\").rstrip(\".\")\n\n self.status = formatted_result\n return [Data(data={\"result\": formatted_result})]\n\n except (SyntaxError, TypeError, KeyError) as e:\n error_message = f\"Invalid expression: {str(e)}\"\n self.status = error_message\n return [Data(data={\"error\": error_message})]\n except ZeroDivisionError:\n error_message = \"Error: Division by zero\"\n self.status = error_message\n return [Data(data={\"error\": error_message})]\n except Exception as e:\n error_message = f\"Error: {str(e)}\"\n self.status = error_message\n return [Data(data={\"error\": error_message})]\n"
|
|
},
|
|
"expression": {
|
|
"_input_type": "MessageTextInput",
|
|
"advanced": false,
|
|
"display_name": "Expression",
|
|
"dynamic": false,
|
|
"info": "The arithmetic expression to evaluate (e.g., '4*4*(33/22)+12-20').",
|
|
"input_types": [
|
|
"Message"
|
|
],
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "expression",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_input": true,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "2+2"
|
|
}
|
|
}
|
|
},
|
|
"type": "CalculatorTool"
|
|
},
|
|
"dragging": false,
|
|
"height": 375,
|
|
"id": "CalculatorTool-Nb4P5",
|
|
"position": {
|
|
"x": 2330.062076024461,
|
|
"y": 429.6717346334192
|
|
},
|
|
"positionAbsolute": {
|
|
"x": 2330.062076024461,
|
|
"y": 429.6717346334192
|
|
},
|
|
"selected": false,
|
|
"type": "genericNode",
|
|
"width": 384
|
|
},
|
|
{
|
|
"data": {
|
|
"description": "A tool for running Python code in a REPL environment.",
|
|
"display_name": "Python REPL Tool",
|
|
"id": "PythonREPLTool-i922a",
|
|
"node": {
|
|
"base_classes": [
|
|
"Data",
|
|
"Tool"
|
|
],
|
|
"beta": false,
|
|
"conditional_paths": [],
|
|
"custom_fields": {},
|
|
"description": "A tool for running Python code in a REPL environment.",
|
|
"display_name": "Python REPL Tool",
|
|
"documentation": "",
|
|
"edited": false,
|
|
"field_order": [
|
|
"name",
|
|
"description",
|
|
"global_imports",
|
|
"code"
|
|
],
|
|
"frozen": false,
|
|
"metadata": {},
|
|
"output_types": [],
|
|
"outputs": [
|
|
{
|
|
"cache": true,
|
|
"display_name": "Data",
|
|
"method": "run_model",
|
|
"name": "api_run_model",
|
|
"required_inputs": [
|
|
"code",
|
|
"description",
|
|
"global_imports",
|
|
"name"
|
|
],
|
|
"selected": "Data",
|
|
"types": [
|
|
"Data"
|
|
],
|
|
"value": "__UNDEFINED__"
|
|
},
|
|
{
|
|
"cache": true,
|
|
"display_name": "Tool",
|
|
"method": "build_tool",
|
|
"name": "api_build_tool",
|
|
"required_inputs": [
|
|
"code",
|
|
"description",
|
|
"global_imports",
|
|
"name"
|
|
],
|
|
"selected": "Tool",
|
|
"types": [
|
|
"Tool"
|
|
],
|
|
"value": "__UNDEFINED__"
|
|
}
|
|
],
|
|
"pinned": false,
|
|
"template": {
|
|
"_type": "Component",
|
|
"code": {
|
|
"advanced": true,
|
|
"dynamic": true,
|
|
"fileTypes": [],
|
|
"file_path": "",
|
|
"info": "",
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"multiline": true,
|
|
"name": "code",
|
|
"password": false,
|
|
"placeholder": "",
|
|
"required": true,
|
|
"show": true,
|
|
"title_case": false,
|
|
"type": "code",
|
|
"value": "import importlib\n\nfrom langchain.tools import StructuredTool\nfrom langchain_experimental.utilities import PythonREPL\nfrom pydantic import BaseModel, Field\n\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.field_typing import Tool\nfrom langflow.inputs import StrInput\nfrom langflow.schema import Data\n\n\nclass PythonREPLToolComponent(LCToolComponent):\n display_name = \"Python REPL Tool\"\n description = \"A tool for running Python code in a REPL environment.\"\n name = \"PythonREPLTool\"\n\n inputs = [\n StrInput(\n name=\"name\",\n display_name=\"Tool Name\",\n info=\"The name of the tool.\",\n value=\"python_repl\",\n ),\n StrInput(\n name=\"description\",\n display_name=\"Tool Description\",\n info=\"A description of the tool.\",\n value=\"A Python shell. Use this to execute python commands. \"\n \"Input should be a valid python command. \"\n \"If you want to see the output of a value, you should print it out with `print(...)`.\",\n ),\n StrInput(\n name=\"global_imports\",\n display_name=\"Global Imports\",\n info=\"A comma-separated list of modules to import globally, e.g. 'math,numpy'.\",\n value=\"math\",\n ),\n StrInput(\n name=\"code\",\n display_name=\"Python Code\",\n info=\"The Python code to execute.\",\n value=\"print('Hello, World!')\",\n ),\n ]\n\n class PythonREPLSchema(BaseModel):\n code: str = Field(..., description=\"The Python code to execute.\")\n\n def get_globals(self, global_imports: str | list[str]) -> dict:\n global_dict = {}\n if isinstance(global_imports, str):\n modules = [module.strip() for module in global_imports.split(\",\")]\n elif isinstance(global_imports, list):\n modules = global_imports\n else:\n msg = \"global_imports must be either a string or a list\"\n raise ValueError(msg)\n\n for module in modules:\n try:\n imported_module = importlib.import_module(module)\n global_dict[imported_module.__name__] = imported_module\n except ImportError:\n msg = f\"Could not import module {module}\"\n raise ImportError(msg)\n return global_dict\n\n def build_tool(self) -> Tool:\n _globals = self.get_globals(self.global_imports)\n python_repl = PythonREPL(_globals=_globals)\n\n def run_python_code(code: str) -> str:\n try:\n return python_repl.run(code)\n except Exception as e:\n return f\"Error: {str(e)}\"\n\n tool = StructuredTool.from_function(\n name=self.name,\n description=self.description,\n func=run_python_code,\n args_schema=self.PythonREPLSchema,\n )\n\n self.status = f\"Python REPL Tool created with global imports: {self.global_imports}\"\n return tool\n\n def run_model(self) -> list[Data]:\n tool = self.build_tool()\n result = tool.run(self.code)\n return [Data(data={\"result\": result})]\n"
|
|
},
|
|
"description": {
|
|
"_input_type": "StrInput",
|
|
"advanced": false,
|
|
"display_name": "Tool Description",
|
|
"dynamic": false,
|
|
"info": "A description of the tool.",
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "description",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "A Python shell. Use this to execute python commands. Input should be a valid python command. If you want to see the output of a value, you should print it out with `print(...)`."
|
|
},
|
|
"global_imports": {
|
|
"_input_type": "StrInput",
|
|
"advanced": false,
|
|
"display_name": "Global Imports",
|
|
"dynamic": false,
|
|
"info": "A comma-separated list of modules to import globally, e.g. 'math,numpy'.",
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "global_imports",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "math"
|
|
},
|
|
"name": {
|
|
"_input_type": "StrInput",
|
|
"advanced": false,
|
|
"display_name": "Tool Name",
|
|
"dynamic": false,
|
|
"info": "The name of the tool.",
|
|
"list": false,
|
|
"load_from_db": false,
|
|
"name": "name",
|
|
"placeholder": "",
|
|
"required": false,
|
|
"show": true,
|
|
"title_case": false,
|
|
"trace_as_metadata": true,
|
|
"type": "str",
|
|
"value": "python_repl"
|
|
}
|
|
}
|
|
},
|
|
"type": "PythonREPLTool"
|
|
},
|
|
"dragging": false,
|
|
"height": 547,
|
|
"id": "PythonREPLTool-i922a",
|
|
"position": {
|
|
"x": 1763.1630547496572,
|
|
"y": 791.8164465037205
|
|
},
|
|
"positionAbsolute": {
|
|
"x": 1763.1630547496572,
|
|
"y": 791.8164465037205
|
|
},
|
|
"selected": true,
|
|
"type": "genericNode",
|
|
"width": 384
|
|
}
|
|
],
|
|
"viewport": {
|
|
"x": -796.2952218140445,
|
|
"y": 174.7919632061971,
|
|
"zoom": 0.6144692758797546
|
|
}
|
|
},
|
|
"description": "Single Agent Flow to get you started. This flow contains a calculator and a Python REPL tool, that could be used by our tool calling agent.",
|
|
"endpoint_name": null,
|
|
"id": "beda74a3-7e03-4c14-a148-a7740e810dbf",
|
|
"is_component": false,
|
|
"last_tested_version": "1.0.17",
|
|
"name": "Simple Agent"
|
|
} |