langflow/src/backend/base/langflow/initial_setup/starter_projects/Agent Flow.json
Gabriel Luiz Freitas Almeida 270f609fe7
refactor: enhance tool creation logic and add FeatureFlags (#3662)
* 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>
2024-10-01 20:58:51 +00:00

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"
}