diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json b/src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json index dd415970b..c74c56ebb 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json @@ -1,287 +1,9 @@ { "data": { - "edges": [ - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "TextInput", - "id": "TextInput-VURDN", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "guidelines", - "id": "Prompt-vFWlB", - "inputTypes": [ - "Message", - "Text" - ], - "type": "str" - } - }, - "id": "reactflow__edge-TextInput-VURDN{œdataTypeœ:œTextInputœ,œidœ:œTextInput-VURDNœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-Prompt-vFWlB{œfieldNameœ:œguidelinesœ,œidœ:œPrompt-vFWlBœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", - "source": "TextInput-VURDN", - "sourceHandle": "{œdataTypeœ: œTextInputœ, œidœ: œTextInput-VURDNœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-vFWlB", - "targetHandle": "{œfieldNameœ: œguidelinesœ, œidœ: œPrompt-vFWlBœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "OpenAIModel", - "id": "OpenAIModel-e0DLW", - "name": "text_output", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "post", - "id": "Prompt-0R6oq", - "inputTypes": [ - "Message", - "Text" - ], - "type": "str" - } - }, - "id": "reactflow__edge-OpenAIModel-e0DLW{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-e0DLWœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-Prompt-0R6oq{œfieldNameœ:œpostœ,œidœ:œPrompt-0R6oqœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", - "source": "OpenAIModel-e0DLW", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-e0DLWœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-0R6oq", - "targetHandle": "{œfieldNameœ: œpostœ, œidœ: œPrompt-0R6oqœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "Prompt", - "id": "Prompt-vFWlB", - "name": "prompt", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "OpenAIModel-e0DLW", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-Prompt-vFWlB{œdataTypeœ:œPromptœ,œidœ:œPrompt-vFWlBœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-e0DLW{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-e0DLWœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "source": "Prompt-vFWlB", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-vFWlBœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-e0DLW", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-e0DLWœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "TavilyAISearch", - "id": "TavilyAISearch-AN1Hv", - "name": "api_build_tool", - "output_types": [ - "Tool" - ] - }, - "targetHandle": { - "fieldName": "tools", - "id": "Agent-9Wf58", - "inputTypes": [ - "Tool" - ], - "type": "other" - } - }, - "id": "reactflow__edge-TavilyAISearch-AN1Hv{œdataTypeœ:œTavilyAISearchœ,œidœ:œTavilyAISearch-AN1Hvœ,œnameœ:œapi_build_toolœ,œoutput_typesœ:[œToolœ]}-Agent-9Wf58{œfieldNameœ:œtoolsœ,œidœ:œAgent-9Wf58œ,œinputTypesœ:[œToolœ,œBaseToolœ,œStructuredToolœ],œtypeœ:œotherœ}", - "selected": false, - "source": "TavilyAISearch-AN1Hv", - "sourceHandle": "{œdataTypeœ: œTavilyAISearchœ, œidœ: œTavilyAISearch-AN1Hvœ, œnameœ: œapi_build_toolœ, œoutput_typesœ: [œToolœ]}", - "target": "Agent-9Wf58", - "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œAgent-9Wf58œ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ChatInput", - "id": "ChatInput-RN2Gt", - "name": "message", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "Agent-9Wf58", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ChatInput-RN2Gt{œdataTypeœ:œChatInputœ,œidœ:œChatInput-RN2Gtœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Agent-9Wf58{œfieldNameœ:œinput_valueœ,œidœ:œAgent-9Wf58œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "source": "ChatInput-RN2Gt", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-RN2Gtœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "Agent-9Wf58", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAgent-9Wf58œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "Agent", - "id": "Agent-9Wf58", - "name": "response", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "context", - "id": "Prompt-vFWlB", - "inputTypes": [ - "Message", - "Text" - ], - "type": "str" - } - }, - "id": "reactflow__edge-Agent-9Wf58{œdataTypeœ:œAgentœ,œidœ:œAgent-9Wf58œ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-Prompt-vFWlB{œfieldNameœ:œcontextœ,œidœ:œPrompt-vFWlBœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", - "source": "Agent-9Wf58", - "sourceHandle": "{œdataTypeœ: œAgentœ, œidœ: œAgent-9Wf58œ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-vFWlB", - "targetHandle": "{œfieldNameœ: œcontextœ, œidœ: œPrompt-vFWlBœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "Prompt", - "id": "Prompt-0R6oq", - "name": "prompt", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "OpenAIModel-XHfFc", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-Prompt-0R6oq{œdataTypeœ:œPromptœ,œidœ:œPrompt-0R6oqœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-XHfFc{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-XHfFcœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "source": "Prompt-0R6oq", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-0R6oqœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-XHfFc", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-XHfFcœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "OpenAIModel", - "id": "OpenAIModel-e0DLW", - "name": "text_output", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "post", - "id": "Prompt-Z1RBN", - "inputTypes": [ - "Message", - "Text" - ], - "type": "str" - } - }, - "id": "reactflow__edge-OpenAIModel-e0DLW{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-e0DLWœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-Prompt-Z1RBN{œfieldNameœ:œpostœ,œidœ:œPrompt-Z1RBNœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", - "source": "OpenAIModel-e0DLW", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-e0DLWœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-Z1RBN", - "targetHandle": "{œfieldNameœ: œpostœ, œidœ: œPrompt-Z1RBNœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "OpenAIModel", - "id": "OpenAIModel-XHfFc", - "name": "text_output", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "image_description", - "id": "Prompt-Z1RBN", - "inputTypes": [ - "Message", - "Text" - ], - "type": "str" - } - }, - "id": "reactflow__edge-OpenAIModel-XHfFc{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-XHfFcœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-Prompt-Z1RBN{œfieldNameœ:œimage_descriptionœ,œidœ:œPrompt-Z1RBNœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", - "source": "OpenAIModel-XHfFc", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-XHfFcœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-Z1RBN", - "targetHandle": "{œfieldNameœ: œimage_descriptionœ, œidœ: œPrompt-Z1RBNœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "Prompt", - "id": "Prompt-Z1RBN", - "name": "prompt", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "ChatOutput-1gPMj", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-Prompt-Z1RBN{œdataTypeœ:œPromptœ,œidœ:œPrompt-Z1RBNœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-1gPMj{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-1gPMjœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "source": "Prompt-Z1RBN", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-Z1RBNœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-1gPMj", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-1gPMjœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - } - ], "nodes": [ { "data": { - "id": "ChatInput-RN2Gt", + "id": "ChatInput-RXwSP", "node": { "base_classes": [ "Message" @@ -553,7 +275,7 @@ }, "dragging": false, "height": 234, - "id": "ChatInput-RN2Gt", + "id": "ChatInput-RXwSP", "position": { "x": 5183.264962599111, "y": 3024.7129453201533 @@ -564,13 +286,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 234 + } }, { "data": { "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", - "id": "Prompt-vFWlB", + "id": "Prompt-kqSxX", "node": { "base_classes": [ "Message" @@ -723,9 +449,9 @@ }, "dragging": false, "height": 433, - "id": "Prompt-vFWlB", + "id": "Prompt-kqSxX", "position": { - "x": 6013.179772864059, + "x": 6044.447585613556, "y": 2937.851014457363 }, "positionAbsolute": { @@ -734,11 +460,15 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 433 + } }, { "data": { - "id": "TextInput-VURDN", + "id": "TextInput-B04zJ", "node": { "base_classes": [ "Message" @@ -821,10 +551,10 @@ }, "dragging": false, "height": 234, - "id": "TextInput-VURDN", + "id": "TextInput-B04zJ", "position": { - "x": 5671.190001393486, - "y": 3422.371192525402 + "x": 5663.277060522892, + "y": 3512.0511890588114 }, "positionAbsolute": { "x": 5671.190001393486, @@ -832,13 +562,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 234 + } }, { "data": { "description": "Generates text using OpenAI LLMs.", "display_name": "OpenAI", - "id": "OpenAIModel-e0DLW", + "id": "OpenAIModel-BOLef", "node": { "base_classes": [ "LanguageModel", @@ -918,7 +652,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -1133,7 +867,7 @@ }, "dragging": false, "height": 543, - "id": "OpenAIModel-e0DLW", + "id": "OpenAIModel-BOLef", "position": { "x": 6427.182886017446, "y": 2891.554378731566 @@ -1144,13 +878,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 543 + } }, { "data": { "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", - "id": "Prompt-0R6oq", + "id": "Prompt-BwI7e", "node": { "base_classes": [ "Message" @@ -1279,10 +1017,10 @@ }, "dragging": false, "height": 347, - "id": "Prompt-0R6oq", + "id": "Prompt-BwI7e", "position": { - "x": 6786.650693383261, - "y": 3042.4668667721307 + "x": 6822.3853365255445, + "y": 3031.299790790167 }, "positionAbsolute": { "x": 6786.650693383261, @@ -1290,13 +1028,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 347 + } }, { "data": { "description": "Display a chat message in the Playground.", "display_name": "Chat Output", - "id": "ChatOutput-1gPMj", + "id": "ChatOutput-jWqJJ", "node": { "base_classes": [ "Message" @@ -1555,7 +1297,7 @@ }, "dragging": false, "height": 234, - "id": "ChatOutput-1gPMj", + "id": "ChatOutput-jWqJJ", "position": { "x": 7980.617825443558, "y": 3377.2219674389726 @@ -1566,13 +1308,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 234 + } }, { "data": { "description": "Define the agent's instructions, then enter a task to complete using tools.", "display_name": "Agent", - "id": "Agent-9Wf58", + "id": "Agent-5FFry", "node": { "base_classes": [ "Message" @@ -1717,7 +1463,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -2130,7 +1876,7 @@ }, "dragging": false, "height": 650, - "id": "Agent-9Wf58", + "id": "Agent-5FFry", "position": { "x": 5665.465212822881, "y": 2760.0819124193113 @@ -2141,25 +1887,223 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 650 + } }, { "data": { "description": "**Tavily AI** is a search engine optimized for LLMs and RAG, aimed at efficient, quick, and persistent search results. It can be used independently or as an agent tool.\n\nNote: Check 'Advanced' for all options.\n", - "display_name": "Tavily AI Search", - "id": "TavilyAISearch-AN1Hv", + "display_name": "Tavily AI Search [DEPRECATED]", + "id": "TavilyAISearch-HpBaM", "node": { + "template": { + "_type": "Component", + "api_key": { + "load_from_db": false, + "required": true, + "placeholder": "", + "show": true, + "name": "api_key", + "value": "", + "display_name": "Tavily API Key", + "advanced": false, + "input_types": [ + "Message" + ], + "dynamic": false, + "info": "Your Tavily API Key.", + "title_case": false, + "password": true, + "type": "str", + "_input_type": "SecretStrInput" + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "from enum import Enum\n\nimport httpx\nfrom langchain.tools import StructuredTool\nfrom langchain_core.tools import ToolException\nfrom loguru import logger\nfrom pydantic import BaseModel, Field\n\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.field_typing import Tool\nfrom langflow.inputs import BoolInput, DropdownInput, IntInput, MessageTextInput, SecretStrInput\nfrom langflow.schema import Data\n\n\nclass TavilySearchDepth(Enum):\n BASIC = \"basic\"\n ADVANCED = \"advanced\"\n\n\nclass TavilySearchTopic(Enum):\n GENERAL = \"general\"\n NEWS = \"news\"\n\n\nclass TavilySearchSchema(BaseModel):\n query: str = Field(..., description=\"The search query you want to execute with Tavily.\")\n search_depth: TavilySearchDepth = Field(TavilySearchDepth.BASIC, description=\"The depth of the search.\")\n topic: TavilySearchTopic = Field(TavilySearchTopic.GENERAL, description=\"The category of the search.\")\n max_results: int = Field(5, description=\"The maximum number of search results to return.\")\n include_images: bool = Field(default=False, description=\"Include a list of query-related images in the response.\")\n include_answer: bool = Field(default=False, description=\"Include a short answer to original query.\")\n\n\nclass TavilySearchToolComponent(LCToolComponent):\n display_name = \"Tavily AI Search [DEPRECATED]\"\n description = \"\"\"**Tavily AI** is a search engine optimized for LLMs and RAG, \\\n aimed at efficient, quick, and persistent search results. It can be used independently or as an agent tool.\n\nNote: Check 'Advanced' for all options.\n\"\"\"\n icon = \"TavilyIcon\"\n name = \"TavilyAISearch\"\n documentation = \"https://docs.tavily.com/\"\n legacy = True\n\n inputs = [\n SecretStrInput(\n name=\"api_key\",\n display_name=\"Tavily API Key\",\n required=True,\n info=\"Your Tavily API Key.\",\n ),\n MessageTextInput(\n name=\"query\",\n display_name=\"Search Query\",\n info=\"The search query you want to execute with Tavily.\",\n ),\n DropdownInput(\n name=\"search_depth\",\n display_name=\"Search Depth\",\n info=\"The depth of the search.\",\n options=list(TavilySearchDepth),\n value=TavilySearchDepth.ADVANCED,\n advanced=True,\n ),\n DropdownInput(\n name=\"topic\",\n display_name=\"Search Topic\",\n info=\"The category of the search.\",\n options=list(TavilySearchTopic),\n value=TavilySearchTopic.GENERAL,\n advanced=True,\n ),\n IntInput(\n name=\"max_results\",\n display_name=\"Max Results\",\n info=\"The maximum number of search results to return.\",\n value=5,\n advanced=True,\n ),\n BoolInput(\n name=\"include_images\",\n display_name=\"Include Images\",\n info=\"Include a list of query-related images in the response.\",\n value=True,\n advanced=True,\n ),\n BoolInput(\n name=\"include_answer\",\n display_name=\"Include Answer\",\n info=\"Include a short answer to original query.\",\n value=True,\n advanced=True,\n ),\n ]\n\n def run_model(self) -> list[Data]:\n # Convert string values to enum instances with validation\n try:\n search_depth_enum = (\n self.search_depth\n if isinstance(self.search_depth, TavilySearchDepth)\n else TavilySearchDepth(str(self.search_depth).lower())\n )\n except ValueError as e:\n error_message = f\"Invalid search depth value: {e!s}\"\n self.status = error_message\n return [Data(data={\"error\": error_message})]\n\n try:\n topic_enum = (\n self.topic if isinstance(self.topic, TavilySearchTopic) else TavilySearchTopic(str(self.topic).lower())\n )\n except ValueError as e:\n error_message = f\"Invalid topic value: {e!s}\"\n self.status = error_message\n return [Data(data={\"error\": error_message})]\n\n return self._tavily_search(\n self.query,\n search_depth=search_depth_enum,\n topic=topic_enum,\n max_results=self.max_results,\n include_images=self.include_images,\n include_answer=self.include_answer,\n )\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"tavily_search\",\n description=\"Perform a web search using the Tavily API.\",\n func=self._tavily_search,\n args_schema=TavilySearchSchema,\n )\n\n def _tavily_search(\n self,\n query: str,\n *,\n search_depth: TavilySearchDepth = TavilySearchDepth.BASIC,\n topic: TavilySearchTopic = TavilySearchTopic.GENERAL,\n max_results: int = 5,\n include_images: bool = False,\n include_answer: bool = False,\n ) -> list[Data]:\n # Validate enum values\n if not isinstance(search_depth, TavilySearchDepth):\n msg = f\"Invalid search_depth value: {search_depth}\"\n raise TypeError(msg)\n if not isinstance(topic, TavilySearchTopic):\n msg = f\"Invalid topic value: {topic}\"\n raise TypeError(msg)\n\n try:\n url = \"https://api.tavily.com/search\"\n headers = {\n \"content-type\": \"application/json\",\n \"accept\": \"application/json\",\n }\n payload = {\n \"api_key\": self.api_key,\n \"query\": query,\n \"search_depth\": search_depth.value,\n \"topic\": topic.value,\n \"max_results\": max_results,\n \"include_images\": include_images,\n \"include_answer\": include_answer,\n }\n\n with httpx.Client() as client:\n response = client.post(url, json=payload, headers=headers)\n\n response.raise_for_status()\n search_results = response.json()\n\n data_results = [\n Data(\n data={\n \"title\": result.get(\"title\"),\n \"url\": result.get(\"url\"),\n \"content\": result.get(\"content\"),\n \"score\": result.get(\"score\"),\n }\n )\n for result in search_results.get(\"results\", [])\n ]\n\n if include_answer and search_results.get(\"answer\"):\n data_results.insert(0, Data(data={\"answer\": search_results[\"answer\"]}))\n\n if include_images and search_results.get(\"images\"):\n data_results.append(Data(data={\"images\": search_results[\"images\"]}))\n\n self.status = data_results # type: ignore[assignment]\n\n except httpx.HTTPStatusError as e:\n error_message = f\"HTTP error: {e.response.status_code} - {e.response.text}\"\n logger.debug(error_message)\n self.status = error_message\n raise ToolException(error_message) from e\n except Exception as e:\n error_message = f\"Unexpected error: {e}\"\n logger.opt(exception=True).debug(\"Error running Tavily Search\")\n self.status = error_message\n raise ToolException(error_message) from e\n return data_results\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "include_answer": { + "tool_mode": false, + "trace_as_metadata": true, + "list": false, + "list_add_label": "Add More", + "required": false, + "placeholder": "", + "show": true, + "name": "include_answer", + "value": true, + "display_name": "Include Answer", + "advanced": true, + "dynamic": false, + "info": "Include a short answer to original query.", + "title_case": false, + "type": "bool", + "_input_type": "BoolInput" + }, + "include_images": { + "tool_mode": false, + "trace_as_metadata": true, + "list": false, + "list_add_label": "Add More", + "required": false, + "placeholder": "", + "show": true, + "name": "include_images", + "value": true, + "display_name": "Include Images", + "advanced": true, + "dynamic": false, + "info": "Include a list of query-related images in the response.", + "title_case": false, + "type": "bool", + "_input_type": "BoolInput" + }, + "max_results": { + "tool_mode": false, + "trace_as_metadata": true, + "list": false, + "list_add_label": "Add More", + "required": false, + "placeholder": "", + "show": true, + "name": "max_results", + "value": 5, + "display_name": "Max Results", + "advanced": true, + "dynamic": false, + "info": "The maximum number of search results to return.", + "title_case": false, + "type": "int", + "_input_type": "IntInput" + }, + "query": { + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "load_from_db": false, + "list": false, + "list_add_label": "Add More", + "required": false, + "placeholder": "", + "show": true, + "name": "query", + "value": "", + "display_name": "Search Query", + "advanced": false, + "input_types": [ + "Message" + ], + "dynamic": false, + "info": "The search query you want to execute with Tavily.", + "title_case": false, + "type": "str", + "_input_type": "MessageTextInput" + }, + "search_depth": { + "tool_mode": false, + "trace_as_metadata": true, + "options": [ + "basic", + "advanced" + ], + "combobox": false, + "required": false, + "placeholder": "", + "show": true, + "name": "search_depth", + "value": "advanced", + "display_name": "Search Depth", + "advanced": true, + "dynamic": false, + "info": "The depth of the search.", + "title_case": false, + "type": "str", + "_input_type": "DropdownInput", + "load_from_db": false + }, + "topic": { + "tool_mode": false, + "trace_as_metadata": true, + "options": [ + "general", + "news" + ], + "combobox": false, + "required": false, + "placeholder": "", + "show": true, + "name": "topic", + "value": "general", + "display_name": "Search Topic", + "advanced": true, + "dynamic": false, + "info": "The category of the search.", + "title_case": false, + "type": "str", + "_input_type": "DropdownInput", + "load_from_db": false + } + }, + "description": "**Tavily AI** is a search engine optimized for LLMs and RAG, aimed at efficient, quick, and persistent search results. It can be used independently or as an agent tool.\n\nNote: Check 'Advanced' for all options.\n", + "icon": "TavilyIcon", "base_classes": [ "Data", "Tool" ], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "**Tavily AI** is a search engine optimized for LLMs and RAG, aimed at efficient, quick, and persistent search results. It can be used independently or as an agent tool.\n\nNote: Check 'Advanced' for all options.\n", - "display_name": "Tavily AI Search", + "display_name": "Tavily AI Search [DEPRECATED]", "documentation": "https://docs.tavily.com/", - "edited": false, + "minimized": false, + "custom_fields": {}, + "output_types": [], + "pinned": false, + "conditional_paths": [], + "frozen": false, + "outputs": [ + { + "types": [ + "Data" + ], + "selected": "Data", + "name": "api_run_model", + "display_name": "Data", + "method": "run_model", + "value": "__UNDEFINED__", + "cache": true, + "required_inputs": [ + "api_key" + ] + }, + { + "types": [ + "Tool" + ], + "selected": "Tool", + "name": "api_build_tool", + "display_name": "Tool", + "method": "build_tool", + "value": "__UNDEFINED__", + "cache": true, + "required_inputs": [ + "api_key" + ] + } + ], "field_order": [ "api_key", "query", @@ -2169,204 +2113,17 @@ "include_images", "include_answer" ], - "frozen": false, - "icon": "TavilyIcon", - "legacy": false, - "lf_version": "1.0.19.post2", + "beta": false, + "legacy": true, + "edited": false, "metadata": {}, - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Data", - "method": "run_model", - "name": "api_run_model", - "required_inputs": [ - "api_key" - ], - "selected": "Data", - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Tool", - "method": "build_tool", - "name": "api_build_tool", - "required_inputs": [ - "api_key" - ], - "selected": "Tool", - "types": [ - "Tool" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "api_key": { - "_input_type": "SecretStrInput", - "advanced": false, - "display_name": "Tavily API Key", - "dynamic": false, - "info": "Your Tavily API Key.", - "input_types": [ - "Message" - ], - "load_from_db": true, - "name": "api_key", - "password": true, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "str", - "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 enum import Enum\n\nimport httpx\nfrom langchain.tools import StructuredTool\nfrom langchain_core.tools import ToolException\nfrom loguru import logger\nfrom pydantic import BaseModel, Field\n\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.field_typing import Tool\nfrom langflow.inputs import BoolInput, DropdownInput, IntInput, MessageTextInput, SecretStrInput\nfrom langflow.schema import Data\n\n\nclass TavilySearchDepth(Enum):\n BASIC = \"basic\"\n ADVANCED = \"advanced\"\n\n\nclass TavilySearchTopic(Enum):\n GENERAL = \"general\"\n NEWS = \"news\"\n\n\nclass TavilySearchSchema(BaseModel):\n query: str = Field(..., description=\"The search query you want to execute with Tavily.\")\n search_depth: TavilySearchDepth = Field(TavilySearchDepth.BASIC, description=\"The depth of the search.\")\n topic: TavilySearchTopic = Field(TavilySearchTopic.GENERAL, description=\"The category of the search.\")\n max_results: int = Field(5, description=\"The maximum number of search results to return.\")\n include_images: bool = Field(default=False, description=\"Include a list of query-related images in the response.\")\n include_answer: bool = Field(default=False, description=\"Include a short answer to original query.\")\n\n\nclass TavilySearchToolComponent(LCToolComponent):\n display_name = \"Tavily AI Search\"\n description = \"\"\"**Tavily AI** is a search engine optimized for LLMs and RAG, \\\n aimed at efficient, quick, and persistent search results. It can be used independently or as an agent tool.\n\nNote: Check 'Advanced' for all options.\n\"\"\"\n icon = \"TavilyIcon\"\n name = \"TavilyAISearch\"\n documentation = \"https://docs.tavily.com/\"\n\n inputs = [\n SecretStrInput(\n name=\"api_key\",\n display_name=\"Tavily API Key\",\n required=True,\n info=\"Your Tavily API Key.\",\n ),\n MessageTextInput(\n name=\"query\",\n display_name=\"Search Query\",\n info=\"The search query you want to execute with Tavily.\",\n ),\n DropdownInput(\n name=\"search_depth\",\n display_name=\"Search Depth\",\n info=\"The depth of the search.\",\n options=list(TavilySearchDepth),\n value=TavilySearchDepth.ADVANCED,\n advanced=True,\n ),\n DropdownInput(\n name=\"topic\",\n display_name=\"Search Topic\",\n info=\"The category of the search.\",\n options=list(TavilySearchTopic),\n value=TavilySearchTopic.GENERAL,\n advanced=True,\n ),\n IntInput(\n name=\"max_results\",\n display_name=\"Max Results\",\n info=\"The maximum number of search results to return.\",\n value=5,\n advanced=True,\n ),\n BoolInput(\n name=\"include_images\",\n display_name=\"Include Images\",\n info=\"Include a list of query-related images in the response.\",\n value=True,\n advanced=True,\n ),\n BoolInput(\n name=\"include_answer\",\n display_name=\"Include Answer\",\n info=\"Include a short answer to original query.\",\n value=True,\n advanced=True,\n ),\n ]\n\n def run_model(self) -> list[Data]:\n # Convert string values to enum instances with validation\n try:\n search_depth_enum = (\n self.search_depth\n if isinstance(self.search_depth, TavilySearchDepth)\n else TavilySearchDepth(str(self.search_depth).lower())\n )\n except ValueError as e:\n error_message = f\"Invalid search depth value: {e!s}\"\n self.status = error_message\n return [Data(data={\"error\": error_message})]\n\n try:\n topic_enum = (\n self.topic if isinstance(self.topic, TavilySearchTopic) else TavilySearchTopic(str(self.topic).lower())\n )\n except ValueError as e:\n error_message = f\"Invalid topic value: {e!s}\"\n self.status = error_message\n return [Data(data={\"error\": error_message})]\n\n return self._tavily_search(\n self.query,\n search_depth=search_depth_enum,\n topic=topic_enum,\n max_results=self.max_results,\n include_images=self.include_images,\n include_answer=self.include_answer,\n )\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"tavily_search\",\n description=\"Perform a web search using the Tavily API.\",\n func=self._tavily_search,\n args_schema=TavilySearchSchema,\n )\n\n def _tavily_search(\n self,\n query: str,\n *,\n search_depth: TavilySearchDepth = TavilySearchDepth.BASIC,\n topic: TavilySearchTopic = TavilySearchTopic.GENERAL,\n max_results: int = 5,\n include_images: bool = False,\n include_answer: bool = False,\n ) -> list[Data]:\n # Validate enum values\n if not isinstance(search_depth, TavilySearchDepth):\n msg = f\"Invalid search_depth value: {search_depth}\"\n raise TypeError(msg)\n if not isinstance(topic, TavilySearchTopic):\n msg = f\"Invalid topic value: {topic}\"\n raise TypeError(msg)\n\n try:\n url = \"https://api.tavily.com/search\"\n headers = {\n \"content-type\": \"application/json\",\n \"accept\": \"application/json\",\n }\n payload = {\n \"api_key\": self.api_key,\n \"query\": query,\n \"search_depth\": search_depth.value,\n \"topic\": topic.value,\n \"max_results\": max_results,\n \"include_images\": include_images,\n \"include_answer\": include_answer,\n }\n\n with httpx.Client() as client:\n response = client.post(url, json=payload, headers=headers)\n\n response.raise_for_status()\n search_results = response.json()\n\n data_results = [\n Data(\n data={\n \"title\": result.get(\"title\"),\n \"url\": result.get(\"url\"),\n \"content\": result.get(\"content\"),\n \"score\": result.get(\"score\"),\n }\n )\n for result in search_results.get(\"results\", [])\n ]\n\n if include_answer and search_results.get(\"answer\"):\n data_results.insert(0, Data(data={\"answer\": search_results[\"answer\"]}))\n\n if include_images and search_results.get(\"images\"):\n data_results.append(Data(data={\"images\": search_results[\"images\"]}))\n\n self.status = data_results # type: ignore[assignment]\n\n except httpx.HTTPStatusError as e:\n error_message = f\"HTTP error: {e.response.status_code} - {e.response.text}\"\n logger.debug(error_message)\n self.status = error_message\n raise ToolException(error_message) from e\n except Exception as e:\n error_message = f\"Unexpected error: {e}\"\n logger.opt(exception=True).debug(\"Error running Tavily Search\")\n self.status = error_message\n raise ToolException(error_message) from e\n return data_results\n" - }, - "include_answer": { - "_input_type": "BoolInput", - "advanced": true, - "display_name": "Include Answer", - "dynamic": false, - "info": "Include a short answer to original query.", - "list": false, - "name": "include_answer", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "bool", - "value": true - }, - "include_images": { - "_input_type": "BoolInput", - "advanced": true, - "display_name": "Include Images", - "dynamic": false, - "info": "Include a list of query-related images in the response.", - "list": false, - "name": "include_images", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "bool", - "value": true - }, - "max_results": { - "_input_type": "IntInput", - "advanced": true, - "display_name": "Max Results", - "dynamic": false, - "info": "The maximum number of search results to return.", - "list": false, - "name": "max_results", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "int", - "value": 5 - }, - "query": { - "_input_type": "MessageTextInput", - "advanced": false, - "display_name": "Search Query", - "dynamic": false, - "info": "The search query you want to execute with Tavily.", - "input_types": [ - "Message" - ], - "list": false, - "load_from_db": false, - "name": "query", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "" - }, - "search_depth": { - "_input_type": "DropdownInput", - "advanced": true, - "combobox": false, - "display_name": "Search Depth", - "dynamic": false, - "info": "The depth of the search.", - "load_from_db": false, - "name": "search_depth", - "options": [ - "basic", - "advanced" - ], - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "advanced" - }, - "topic": { - "_input_type": "DropdownInput", - "advanced": true, - "combobox": false, - "display_name": "Search Topic", - "dynamic": false, - "info": "The category of the search.", - "load_from_db": false, - "name": "topic", - "options": [ - "general", - "news" - ], - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "general" - } - }, "tool_mode": false }, "type": "TavilyAISearch" }, "dragging": false, "height": 481, - "id": "TavilyAISearch-AN1Hv", + "id": "TavilyAISearch-HpBaM", "position": { "x": 5178.005987190226, "y": 3496.7214582697484 @@ -2377,13 +2134,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 481 + } }, { "data": { "description": "Generates text using OpenAI LLMs.", "display_name": "OpenAI", - "id": "OpenAIModel-XHfFc", + "id": "OpenAIModel-5vp3N", "node": { "base_classes": [ "LanguageModel", @@ -2463,7 +2224,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -2678,7 +2439,7 @@ }, "dragging": false, "height": 543, - "id": "OpenAIModel-XHfFc", + "id": "OpenAIModel-5vp3N", "position": { "x": 7211.829041441037, "y": 2938.1023670807563 @@ -2689,13 +2450,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 543 + } }, { "data": { "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", - "id": "Prompt-Z1RBN", + "id": "Prompt-1yGW4", "node": { "base_classes": [ "Message" @@ -2848,7 +2613,7 @@ }, "dragging": false, "height": 433, - "id": "Prompt-Z1RBN", + "id": "Prompt-1yGW4", "position": { "x": 7613.837241084599, "y": 3139.8282595890087 @@ -2859,11 +2624,15 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 433 + } }, { "data": { - "id": "note-Jr7lC", + "id": "note-xa2dd", "node": { "description": "# Instagram Copywriter \n\nWelcome to the Instagram Copywriter! This flow helps you create compelling Instagram posts with AI-generated content and image prompts.\n\n## Instructions\n1. Enter Your Topic\n - In the Chat Input, enter a brief description of the topic you want to post about.\n - Example: \"Create a post about meditation and its benefits\"\n\n2. Review the Generated Content\n - The flow will use AI to research your topic and generate a formatted Instagram post.\n - The post will include an opening line, main content, emojis, a call-to-action, and hashtags.\n\n3. Check the Image Prompt\n - The flow will also generate a detailed image prompt based on your post content.\n - This prompt can be used with image generation tools to create a matching visual.\n\n4. Copy the Final Output\n - The Chat Output will display the complete Instagram post text followed by the image generation prompt.\n - Copy this output to use in your Instagram content creation process.\n\n5. Refine if Needed\n - If you're not satisfied with the result, you can adjust the input or modify the OpenAI model settings for different outputs.\n\nRemember: Keep your initial topic input clear and concise for best results! 🎨✨", "display_name": "", @@ -2876,7 +2645,7 @@ }, "dragging": false, "height": 648, - "id": "note-Jr7lC", + "id": "note-xa2dd", "position": { "x": 4492.051129290571, "y": 2746.336592524463 @@ -2892,11 +2661,15 @@ "width": 554 }, "type": "noteNode", - "width": 554 + "width": 554, + "measured": { + "width": 328, + "height": 648 + } }, { "data": { - "id": "note-tWoba", + "id": "note-Odqui", "node": { "description": "**Text Input (Guidelines Prompt)**\n - NOTE: \"Contains Instagram post formatting rules. Don't modify this component as it maintains format consistency.\"\n - Maintains fixed guidelines for:\n * Opening structure\n * Main content\n * Emoji usage\n * Call to Action (CTA)\n * Hashtags\n\n4. **First Prompt + OpenAI Sequence**\n - NOTE: \"Generates initial post content following Instagram guidelines\"\n - Settings:\n * Temperature: 0.7 (good balance between creativity and consistency)\n * Input: Receives research context\n * Output: Generates formatted post text\n\n", "display_name": "", @@ -2909,7 +2682,7 @@ }, "dragging": false, "height": 325, - "id": "note-tWoba", + "id": "note-Odqui", "position": { "x": 5667.476249937603, "y": 3644.9055828357396 @@ -2921,11 +2694,15 @@ "resizing": false, "selected": false, "type": "noteNode", - "width": 325 + "width": 325, + "measured": { + "width": 328, + "height": 325 + } }, { "data": { - "id": "note-9ABdX", + "id": "note-uwin1", "node": { "description": "**Second Prompt + OpenAI Sequence**\n - NOTE: \"Transforms the generated post into a prompt for image generation\"\n - Settings:\n * Temperature: 0.7\n * Input: Receives generated post\n * Output: Creates detailed description for image generation\n\n", "display_name": "", @@ -2938,7 +2715,7 @@ }, "dragging": false, "height": 325, - "id": "note-9ABdX", + "id": "note-uwin1", "position": { "x": 6786.375917286389, "y": 3393.8522072000146 @@ -2949,11 +2726,15 @@ }, "selected": false, "type": "noteNode", - "width": 325 + "width": 325, + "measured": { + "width": 328, + "height": 325 + } }, { "data": { - "id": "note-aplGD", + "id": "note-GVjGk", "node": { "description": "**Final Prompt**\n - NOTE: \"Combines Instagram post with image prompt in a final format\"\n - Structure:\n * First part: Complete Instagram post\n * Second part: Image generation prompt\n * Separator: Uses \"**Prompt:**\" to divide sections\n\n7. **Chat Output (Final Output)**\n - NOTE: \"Presents the combined final result that can be copied and used directly\"\n\nGENERAL USAGE TIPS:\n- Keep initial inputs clear and specific\n- Don't modify pre-defined Instagram guidelines\n- If style adjustments are needed, only modify the OpenAI models' temperature\n- Verify all connections are correct before running\n- Final result will always have two parts: post + image prompt\n\nFLOW CONSIDERATIONS:\n- All tools connect only to the Tool Calling Agent\n- The flow is unidirectional (no loops)\n- Each prompt template maintains specific formatting\n- Temperatures are set for optimal creativity/consistency balance\n\nTROUBLESHOOTING NOTES:\n- If output is too creative: Lower temperature", "display_name": "", @@ -2966,7 +2747,7 @@ }, "dragging": false, "height": 325, - "id": "note-aplGD", + "id": "note-GVjGk", "position": { "x": 7606.419013912975, "y": 3612.8149429707646 @@ -2977,11 +2758,15 @@ }, "selected": false, "type": "noteNode", - "width": 325 + "width": 325, + "measured": { + "width": 328, + "height": 325 + } }, { "data": { - "id": "note-AKIwx", + "id": "note-PjdDf", "node": { "description": "# 🔑 Tavily AI Search Needs API Key\n\nYou can get 1000 searches/month free [here](https://tavily.com/) ", "display_name": "", @@ -2994,7 +2779,7 @@ }, "dragging": false, "height": 325, - "id": "note-AKIwx", + "id": "note-PjdDf", "position": { "x": 5174.678177457385, "y": 3339.6628854203204 @@ -3005,13 +2790,295 @@ }, "selected": false, "type": "noteNode", - "width": 325 + "width": 325, + "measured": { + "width": 328, + "height": 325 + } + } + ], + "edges": [ + { + "animated": false, + "className": "not-running", + "data": { + "sourceHandle": { + "dataType": "TextInput", + "id": "TextInput-B04zJ", + "name": "text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "guidelines", + "id": "Prompt-kqSxX", + "inputTypes": [ + "Message", + "Text" + ], + "type": "str" + } + }, + "id": "reactflow__edge-TextInput-B04zJ{œdataTypeœ:œTextInputœ,œidœ:œTextInput-B04zJœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-Prompt-kqSxX{œfieldNameœ:œguidelinesœ,œidœ:œPrompt-kqSxXœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "source": "TextInput-B04zJ", + "sourceHandle": "{œdataTypeœ:œTextInputœ,œidœ:œTextInput-B04zJœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}", + "target": "Prompt-kqSxX", + "targetHandle": "{œfieldNameœ:œguidelinesœ,œidœ:œPrompt-kqSxXœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "animated": false, + "className": "not-running", + "data": { + "sourceHandle": { + "dataType": "OpenAIModel", + "id": "OpenAIModel-BOLef", + "name": "text_output", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "post", + "id": "Prompt-BwI7e", + "inputTypes": [ + "Message", + "Text" + ], + "type": "str" + } + }, + "id": "reactflow__edge-OpenAIModel-BOLef{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-BOLefœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-Prompt-BwI7e{œfieldNameœ:œpostœ,œidœ:œPrompt-BwI7eœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "source": "OpenAIModel-BOLef", + "sourceHandle": "{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-BOLefœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}", + "target": "Prompt-BwI7e", + "targetHandle": "{œfieldNameœ:œpostœ,œidœ:œPrompt-BwI7eœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "animated": false, + "className": "not-running", + "data": { + "sourceHandle": { + "dataType": "Prompt", + "id": "Prompt-kqSxX", + "name": "prompt", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-BOLef", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-Prompt-kqSxX{œdataTypeœ:œPromptœ,œidœ:œPrompt-kqSxXœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-BOLef{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-BOLefœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "source": "Prompt-kqSxX", + "sourceHandle": "{œdataTypeœ:œPromptœ,œidœ:œPrompt-kqSxXœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}", + "target": "OpenAIModel-BOLef", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-BOLefœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" + }, + { + "animated": false, + "className": "not-running", + "data": { + "sourceHandle": { + "dataType": "TavilyAISearch", + "id": "TavilyAISearch-HpBaM", + "name": "api_build_tool", + "output_types": [ + "Tool" + ] + }, + "targetHandle": { + "fieldName": "tools", + "id": "Agent-5FFry", + "inputTypes": [ + "Tool" + ], + "type": "other" + } + }, + "id": "reactflow__edge-TavilyAISearch-HpBaM{œdataTypeœ:œTavilyAISearchœ,œidœ:œTavilyAISearch-HpBaMœ,œnameœ:œapi_build_toolœ,œoutput_typesœ:[œToolœ]}-Agent-5FFry{œfieldNameœ:œtoolsœ,œidœ:œAgent-5FFryœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", + "selected": false, + "source": "TavilyAISearch-HpBaM", + "sourceHandle": "{œdataTypeœ:œTavilyAISearchœ,œidœ:œTavilyAISearch-HpBaMœ,œnameœ:œapi_build_toolœ,œoutput_typesœ:[œToolœ]}", + "target": "Agent-5FFry", + "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgent-5FFryœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" + }, + { + "animated": false, + "className": "not-running", + "data": { + "sourceHandle": { + "dataType": "ChatInput", + "id": "ChatInput-RXwSP", + "name": "message", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "Agent-5FFry", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-ChatInput-RXwSP{œdataTypeœ:œChatInputœ,œidœ:œChatInput-RXwSPœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Agent-5FFry{œfieldNameœ:œinput_valueœ,œidœ:œAgent-5FFryœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "source": "ChatInput-RXwSP", + "sourceHandle": "{œdataTypeœ:œChatInputœ,œidœ:œChatInput-RXwSPœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}", + "target": "Agent-5FFry", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAgent-5FFryœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" + }, + { + "animated": false, + "className": "not-running", + "data": { + "sourceHandle": { + "dataType": "Agent", + "id": "Agent-5FFry", + "name": "response", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "context", + "id": "Prompt-kqSxX", + "inputTypes": [ + "Message", + "Text" + ], + "type": "str" + } + }, + "id": "reactflow__edge-Agent-5FFry{œdataTypeœ:œAgentœ,œidœ:œAgent-5FFryœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-Prompt-kqSxX{œfieldNameœ:œcontextœ,œidœ:œPrompt-kqSxXœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "source": "Agent-5FFry", + "sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-5FFryœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}", + "target": "Prompt-kqSxX", + "targetHandle": "{œfieldNameœ:œcontextœ,œidœ:œPrompt-kqSxXœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "animated": false, + "className": "ran", + "data": { + "sourceHandle": { + "dataType": "Prompt", + "id": "Prompt-BwI7e", + "name": "prompt", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-5vp3N", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-Prompt-BwI7e{œdataTypeœ:œPromptœ,œidœ:œPrompt-BwI7eœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-5vp3N{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-5vp3Nœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "source": "Prompt-BwI7e", + "sourceHandle": "{œdataTypeœ:œPromptœ,œidœ:œPrompt-BwI7eœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}", + "target": "OpenAIModel-5vp3N", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-5vp3Nœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" + }, + { + "animated": false, + "className": "not-running", + "data": { + "sourceHandle": { + "dataType": "OpenAIModel", + "id": "OpenAIModel-BOLef", + "name": "text_output", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "post", + "id": "Prompt-1yGW4", + "inputTypes": [ + "Message", + "Text" + ], + "type": "str" + } + }, + "id": "reactflow__edge-OpenAIModel-BOLef{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-BOLefœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-Prompt-1yGW4{œfieldNameœ:œpostœ,œidœ:œPrompt-1yGW4œ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "source": "OpenAIModel-BOLef", + "sourceHandle": "{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-BOLefœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}", + "target": "Prompt-1yGW4", + "targetHandle": "{œfieldNameœ:œpostœ,œidœ:œPrompt-1yGW4œ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "animated": true, + "className": "running", + "data": { + "sourceHandle": { + "dataType": "OpenAIModel", + "id": "OpenAIModel-5vp3N", + "name": "text_output", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "image_description", + "id": "Prompt-1yGW4", + "inputTypes": [ + "Message", + "Text" + ], + "type": "str" + } + }, + "id": "reactflow__edge-OpenAIModel-5vp3N{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-5vp3Nœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-Prompt-1yGW4{œfieldNameœ:œimage_descriptionœ,œidœ:œPrompt-1yGW4œ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "source": "OpenAIModel-5vp3N", + "sourceHandle": "{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-5vp3Nœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}", + "target": "Prompt-1yGW4", + "targetHandle": "{œfieldNameœ:œimage_descriptionœ,œidœ:œPrompt-1yGW4œ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}" + }, + { + "animated": false, + "className": "not-running", + "data": { + "sourceHandle": { + "dataType": "Prompt", + "id": "Prompt-1yGW4", + "name": "prompt", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-jWqJJ", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-Prompt-1yGW4{œdataTypeœ:œPromptœ,œidœ:œPrompt-1yGW4œ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-jWqJJ{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-jWqJJœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "source": "Prompt-1yGW4", + "sourceHandle": "{œdataTypeœ:œPromptœ,œidœ:œPrompt-1yGW4œ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}", + "target": "ChatOutput-jWqJJ", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-jWqJJœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" } ], "viewport": { - "x": -1826.8109854875006, - "y": -1023.2049813606079, - "zoom": 0.4417458816510278 + "x": -2191.179445453401, + "y": -1055.6007314515284, + "zoom": 0.4477447818995538 } }, "description": " Create engaging Instagram posts with AI-generated content and image prompts, streamlining social media content creation.", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Market Research.json b/src/backend/base/langflow/initial_setup/starter_projects/Market Research.json index b0b6f63c6..2294e2548 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Market Research.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Market Research.json @@ -1,181 +1,11 @@ { "data": { - "edges": [ - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "OpenAIModel", - "id": "OpenAIModel-1WzgM", - "name": "model_output", - "output_types": [ - "LanguageModel" - ] - }, - "targetHandle": { - "fieldName": "llm", - "id": "StructuredOutputComponent-421WY", - "inputTypes": [ - "LanguageModel" - ], - "type": "other" - } - }, - "id": "reactflow__edge-OpenAIModel-1WzgM{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-1WzgMœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutputComponent-421WY{œfieldNameœ:œllmœ,œidœ:œStructuredOutputComponent-421WYœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", - "selected": false, - "source": "OpenAIModel-1WzgM", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-1WzgMœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", - "target": "StructuredOutputComponent-421WY", - "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œStructuredOutputComponent-421WYœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "StructuredOutputComponent", - "id": "StructuredOutputComponent-421WY", - "name": "structured_output", - "output_types": [ - "Data" - ] - }, - "targetHandle": { - "fieldName": "data", - "id": "ParseData-rO6Qs", - "inputTypes": [ - "Data" - ], - "type": "other" - } - }, - "id": "reactflow__edge-StructuredOutputComponent-421WY{œdataTypeœ:œStructuredOutputComponentœ,œidœ:œStructuredOutputComponent-421WYœ,œnameœ:œstructured_outputœ,œoutput_typesœ:[œDataœ]}-ParseData-rO6Qs{œfieldNameœ:œdataœ,œidœ:œParseData-rO6Qsœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", - "selected": false, - "source": "StructuredOutputComponent-421WY", - "sourceHandle": "{œdataTypeœ: œStructuredOutputComponentœ, œidœ: œStructuredOutputComponent-421WYœ, œnameœ: œstructured_outputœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-rO6Qs", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-rO6Qsœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-rO6Qs", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "ChatOutput-hBRXA", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-rO6Qs{œdataTypeœ:œParseDataœ,œidœ:œParseData-rO6Qsœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-hBRXA{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-hBRXAœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-rO6Qs", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-rO6Qsœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-hBRXA", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-hBRXAœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "TavilyAISearch", - "id": "TavilyAISearch-ghguc", - "name": "api_build_tool", - "output_types": [ - "Tool" - ] - }, - "targetHandle": { - "fieldName": "tools", - "id": "Agent-QSS16", - "inputTypes": [ - "Tool" - ], - "type": "other" - } - }, - "id": "reactflow__edge-TavilyAISearch-ghguc{œdataTypeœ:œTavilyAISearchœ,œidœ:œTavilyAISearch-ghgucœ,œnameœ:œapi_build_toolœ,œoutput_typesœ:[œToolœ]}-Agent-QSS16{œfieldNameœ:œtoolsœ,œidœ:œAgent-QSS16œ,œinputTypesœ:[œToolœ,œBaseToolœ,œStructuredToolœ],œtypeœ:œotherœ}", - "selected": false, - "source": "TavilyAISearch-ghguc", - "sourceHandle": "{œdataTypeœ: œTavilyAISearchœ, œidœ: œTavilyAISearch-ghgucœ, œnameœ: œapi_build_toolœ, œoutput_typesœ: [œToolœ]}", - "target": "Agent-QSS16", - "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œAgent-QSS16œ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ChatInput", - "id": "ChatInput-1iaFN", - "name": "message", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "Agent-QSS16", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ChatInput-1iaFN{œdataTypeœ:œChatInputœ,œidœ:œChatInput-1iaFNœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Agent-QSS16{œfieldNameœ:œinput_valueœ,œidœ:œAgent-QSS16œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ChatInput-1iaFN", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-1iaFNœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "Agent-QSS16", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAgent-QSS16œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "Agent", - "id": "Agent-QSS16", - "name": "response", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "StructuredOutputComponent-421WY", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-Agent-QSS16{œdataTypeœ:œAgentœ,œidœ:œAgent-QSS16œ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-StructuredOutputComponent-421WY{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutputComponent-421WYœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "Agent-QSS16", - "sourceHandle": "{œdataTypeœ: œAgentœ, œidœ: œAgent-QSS16œ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}", - "target": "StructuredOutputComponent-421WY", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œStructuredOutputComponent-421WYœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - } - ], "nodes": [ { "data": { "description": "Get chat inputs from the Playground.", "display_name": "Chat Input", - "id": "ChatInput-1iaFN", + "id": "ChatInput-N6esY", "node": { "base_classes": [ "Message" @@ -201,7 +31,7 @@ "frozen": false, "icon": "MessagesSquare", "legacy": false, - "lf_version": "1.0.19.post2", + "lf_version": "1.1.1", "metadata": {}, "output_types": [], "outputs": [ @@ -447,7 +277,7 @@ }, "dragging": false, "height": 234, - "id": "ChatInput-1iaFN", + "id": "ChatInput-N6esY", "position": { "x": 472.38251755471583, "y": 889.8398446936101 @@ -458,13 +288,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 234 + } }, { "data": { "description": "Display a chat message in the Playground.", "display_name": "Chat Output", - "id": "ChatOutput-hBRXA", + "id": "ChatOutput-NJfzg", "node": { "base_classes": [ "Message" @@ -724,7 +558,7 @@ }, "dragging": false, "height": 234, - "id": "ChatOutput-hBRXA", + "id": "ChatOutput-NJfzg", "position": { "x": 2518.282039019285, "y": 855.3686932779933 @@ -735,247 +569,15 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 234 + } }, { "data": { - "description": "**Tavily AI** is a search engine optimized for LLMs and RAG, aimed at efficient, quick, and persistent search results. It can be used independently or as an agent tool.\n\nNote: Check 'Advanced' for all options.\n", - "display_name": "Tavily AI Search", - "id": "TavilyAISearch-ghguc", - "node": { - "base_classes": [ - "Data", - "Tool" - ], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "**Tavily AI** is a search engine optimized for LLMs and RAG, aimed at efficient, quick, and persistent search results. It can be used independently or as an agent tool.\n\nNote: Check 'Advanced' for all options.\n", - "display_name": "Tavily AI Search", - "documentation": "https://docs.tavily.com/", - "edited": false, - "field_order": [ - "api_key", - "query", - "search_depth", - "topic", - "max_results", - "include_images", - "include_answer" - ], - "frozen": false, - "icon": "TavilyIcon", - "legacy": false, - "lf_version": "1.0.19.post2", - "metadata": {}, - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Data", - "method": "run_model", - "name": "api_run_model", - "required_inputs": [ - "api_key" - ], - "selected": "Data", - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Tool", - "method": "build_tool", - "name": "api_build_tool", - "required_inputs": [ - "api_key" - ], - "selected": "Tool", - "types": [ - "Tool" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "api_key": { - "_input_type": "SecretStrInput", - "advanced": false, - "display_name": "Tavily API Key", - "dynamic": false, - "info": "Your Tavily API Key.", - "input_types": [ - "Message" - ], - "load_from_db": true, - "name": "api_key", - "password": true, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "str", - "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 enum import Enum\n\nimport httpx\nfrom langchain.tools import StructuredTool\nfrom langchain_core.tools import ToolException\nfrom loguru import logger\nfrom pydantic import BaseModel, Field\n\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.field_typing import Tool\nfrom langflow.inputs import BoolInput, DropdownInput, IntInput, MessageTextInput, SecretStrInput\nfrom langflow.schema import Data\n\n\nclass TavilySearchDepth(Enum):\n BASIC = \"basic\"\n ADVANCED = \"advanced\"\n\n\nclass TavilySearchTopic(Enum):\n GENERAL = \"general\"\n NEWS = \"news\"\n\n\nclass TavilySearchSchema(BaseModel):\n query: str = Field(..., description=\"The search query you want to execute with Tavily.\")\n search_depth: TavilySearchDepth = Field(TavilySearchDepth.BASIC, description=\"The depth of the search.\")\n topic: TavilySearchTopic = Field(TavilySearchTopic.GENERAL, description=\"The category of the search.\")\n max_results: int = Field(5, description=\"The maximum number of search results to return.\")\n include_images: bool = Field(default=False, description=\"Include a list of query-related images in the response.\")\n include_answer: bool = Field(default=False, description=\"Include a short answer to original query.\")\n\n\nclass TavilySearchToolComponent(LCToolComponent):\n display_name = \"Tavily AI Search\"\n description = \"\"\"**Tavily AI** is a search engine optimized for LLMs and RAG, \\\n aimed at efficient, quick, and persistent search results. It can be used independently or as an agent tool.\n\nNote: Check 'Advanced' for all options.\n\"\"\"\n icon = \"TavilyIcon\"\n name = \"TavilyAISearch\"\n documentation = \"https://docs.tavily.com/\"\n\n inputs = [\n SecretStrInput(\n name=\"api_key\",\n display_name=\"Tavily API Key\",\n required=True,\n info=\"Your Tavily API Key.\",\n ),\n MessageTextInput(\n name=\"query\",\n display_name=\"Search Query\",\n info=\"The search query you want to execute with Tavily.\",\n ),\n DropdownInput(\n name=\"search_depth\",\n display_name=\"Search Depth\",\n info=\"The depth of the search.\",\n options=list(TavilySearchDepth),\n value=TavilySearchDepth.ADVANCED,\n advanced=True,\n ),\n DropdownInput(\n name=\"topic\",\n display_name=\"Search Topic\",\n info=\"The category of the search.\",\n options=list(TavilySearchTopic),\n value=TavilySearchTopic.GENERAL,\n advanced=True,\n ),\n IntInput(\n name=\"max_results\",\n display_name=\"Max Results\",\n info=\"The maximum number of search results to return.\",\n value=5,\n advanced=True,\n ),\n BoolInput(\n name=\"include_images\",\n display_name=\"Include Images\",\n info=\"Include a list of query-related images in the response.\",\n value=True,\n advanced=True,\n ),\n BoolInput(\n name=\"include_answer\",\n display_name=\"Include Answer\",\n info=\"Include a short answer to original query.\",\n value=True,\n advanced=True,\n ),\n ]\n\n def run_model(self) -> list[Data]:\n # Convert string values to enum instances with validation\n try:\n search_depth_enum = (\n self.search_depth\n if isinstance(self.search_depth, TavilySearchDepth)\n else TavilySearchDepth(str(self.search_depth).lower())\n )\n except ValueError as e:\n error_message = f\"Invalid search depth value: {e!s}\"\n self.status = error_message\n return [Data(data={\"error\": error_message})]\n\n try:\n topic_enum = (\n self.topic if isinstance(self.topic, TavilySearchTopic) else TavilySearchTopic(str(self.topic).lower())\n )\n except ValueError as e:\n error_message = f\"Invalid topic value: {e!s}\"\n self.status = error_message\n return [Data(data={\"error\": error_message})]\n\n return self._tavily_search(\n self.query,\n search_depth=search_depth_enum,\n topic=topic_enum,\n max_results=self.max_results,\n include_images=self.include_images,\n include_answer=self.include_answer,\n )\n\n def build_tool(self) -> Tool:\n return StructuredTool.from_function(\n name=\"tavily_search\",\n description=\"Perform a web search using the Tavily API.\",\n func=self._tavily_search,\n args_schema=TavilySearchSchema,\n )\n\n def _tavily_search(\n self,\n query: str,\n *,\n search_depth: TavilySearchDepth = TavilySearchDepth.BASIC,\n topic: TavilySearchTopic = TavilySearchTopic.GENERAL,\n max_results: int = 5,\n include_images: bool = False,\n include_answer: bool = False,\n ) -> list[Data]:\n # Validate enum values\n if not isinstance(search_depth, TavilySearchDepth):\n msg = f\"Invalid search_depth value: {search_depth}\"\n raise TypeError(msg)\n if not isinstance(topic, TavilySearchTopic):\n msg = f\"Invalid topic value: {topic}\"\n raise TypeError(msg)\n\n try:\n url = \"https://api.tavily.com/search\"\n headers = {\n \"content-type\": \"application/json\",\n \"accept\": \"application/json\",\n }\n payload = {\n \"api_key\": self.api_key,\n \"query\": query,\n \"search_depth\": search_depth.value,\n \"topic\": topic.value,\n \"max_results\": max_results,\n \"include_images\": include_images,\n \"include_answer\": include_answer,\n }\n\n with httpx.Client() as client:\n response = client.post(url, json=payload, headers=headers)\n\n response.raise_for_status()\n search_results = response.json()\n\n data_results = [\n Data(\n data={\n \"title\": result.get(\"title\"),\n \"url\": result.get(\"url\"),\n \"content\": result.get(\"content\"),\n \"score\": result.get(\"score\"),\n }\n )\n for result in search_results.get(\"results\", [])\n ]\n\n if include_answer and search_results.get(\"answer\"):\n data_results.insert(0, Data(data={\"answer\": search_results[\"answer\"]}))\n\n if include_images and search_results.get(\"images\"):\n data_results.append(Data(data={\"images\": search_results[\"images\"]}))\n\n self.status = data_results # type: ignore[assignment]\n\n except httpx.HTTPStatusError as e:\n error_message = f\"HTTP error: {e.response.status_code} - {e.response.text}\"\n logger.debug(error_message)\n self.status = error_message\n raise ToolException(error_message) from e\n except Exception as e:\n error_message = f\"Unexpected error: {e}\"\n logger.opt(exception=True).debug(\"Error running Tavily Search\")\n self.status = error_message\n raise ToolException(error_message) from e\n return data_results\n" - }, - "include_answer": { - "_input_type": "BoolInput", - "advanced": true, - "display_name": "Include Answer", - "dynamic": false, - "info": "Include a short answer to original query.", - "list": false, - "name": "include_answer", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "bool", - "value": true - }, - "include_images": { - "_input_type": "BoolInput", - "advanced": true, - "display_name": "Include Images", - "dynamic": false, - "info": "Include a list of query-related images in the response.", - "list": false, - "name": "include_images", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "bool", - "value": true - }, - "max_results": { - "_input_type": "IntInput", - "advanced": true, - "display_name": "Max Results", - "dynamic": false, - "info": "The maximum number of search results to return.", - "list": false, - "name": "max_results", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "int", - "value": 5 - }, - "query": { - "_input_type": "MessageTextInput", - "advanced": false, - "display_name": "Search Query", - "dynamic": false, - "info": "The search query you want to execute with Tavily.", - "input_types": [ - "Message" - ], - "list": false, - "load_from_db": false, - "name": "query", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "" - }, - "search_depth": { - "_input_type": "DropdownInput", - "advanced": true, - "combobox": false, - "display_name": "Search Depth", - "dynamic": false, - "info": "The depth of the search.", - "load_from_db": false, - "name": "search_depth", - "options": [ - "basic", - "advanced" - ], - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "advanced" - }, - "topic": { - "_input_type": "DropdownInput", - "advanced": true, - "combobox": false, - "display_name": "Search Topic", - "dynamic": false, - "info": "The category of the search.", - "load_from_db": false, - "name": "topic", - "options": [ - "general", - "news" - ], - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "general" - } - }, - "tool_mode": false - }, - "type": "TavilyAISearch" - }, - "dragging": false, - "height": 481, - "id": "TavilyAISearch-ghguc", - "position": { - "x": 928.3794352018558, - "y": 797.2042255200732 - }, - "positionAbsolute": { - "x": 928.3794352018558, - "y": 797.2042255200732 - }, - "selected": false, - "type": "genericNode", - "width": 320 - }, - { - "data": { - "id": "note-Fs2b3", + "id": "note-40RoE", "node": { "description": "The StructuredOutputComponent, when utilized with our company information schema, performs the following functions:\n\n1. Accepts an input query regarding a company.\n2. Employs a Language Model (LLM) to analyze the query.\n3. Instructs the LLM to generate a structured response adhering to the predefined schema:\n - Domain\n - LinkedIn URL\n - Cheapest Plan\n - Has Free Trial\n - Has Enterprise Plan\n - Has API\n - Market\n - Pricing Tiers\n - Key Features\n - Target Industries\n\n4. Validates the LLM output against this schema.\n5. Returns a Data object containing the company information structured according to the schema.\n\nIn essence, this component transforms a free-text query about a company into a structured, consistent dataset, facilitating subsequent analysis and application of the information.", "display_name": "", @@ -988,7 +590,7 @@ }, "dragging": false, "height": 403, - "id": "note-Fs2b3", + "id": "note-40RoE", "position": { "x": 2089.5869930853464, "y": 311.41660832449514 @@ -1004,11 +606,15 @@ "width": 461 }, "type": "noteNode", - "width": 461 + "width": 461, + "measured": { + "width": 328, + "height": 403 + } }, { "data": { - "id": "note-BfWWs", + "id": "note-hgOqR", "node": { "description": "PURPOSE:\nConverts unstructured company research into standardized JSON format\n\nKEY FUNCTIONS:\n- Extracts specific business data points\n- Validates and formats information\n- Ensures data consistency\n\nINPUT:\n- Raw company research data\n\nOUTPUT:\nStructured JSON with:\n- Domain information\n- Social links\n- Pricing details\n- Feature availability\n- Market classification\n- Product features\n- Industry focus\n\nRULES:\n1. Uses strict boolean values\n2. Standardizes pricing formats\n3. Validates market categories\n4. Handles missing data consistently", "display_name": "", @@ -1021,7 +627,7 @@ }, "dragging": false, "height": 382, - "id": "note-BfWWs", + "id": "note-hgOqR", "position": { "x": 1237.6627823432912, "y": 111.53860932079613 @@ -1037,11 +643,15 @@ "width": 398 }, "type": "noteNode", - "width": 398 + "width": 398, + "measured": { + "width": 328, + "height": 382 + } }, { "data": { - "id": "note-iNLPA", + "id": "note-ifPGq", "node": { "description": "# Market Research\nThis flow helps you gather comprehensive information about companies for sales and business intelligence purposes.\n\n## Instructions\n\n1. Enter Company Name\n - In the Chat Input node, type the name of the company you want to research\n - Example inputs: \"Salesforce.com\", \"Shopify\", \"Zoom Video Communications\"\n\n2. Initiate Research\n - The Agent will use the Tavily AI Search tool to gather information\n - It will focus on key areas like pricing, features, and market positioning\n\n3. Review Structured Output\n - The flow will generate a structured JSON output with standardized fields\n - This includes domain, LinkedIn URL, pricing details, and key features\n\n4. Examine Formatted Results\n - The Parse Data component will convert the JSON into a readable format\n - You'll see a comprehensive company profile with organized sections\n\n5. Analyze and Use Data\n - Use the generated information for sales prospecting, competitive analysis, or market research\n - The structured format allows for easy comparison between different companies\n\nRemember: Always verify critical information from official sources before making business decisions! 🔍💼", "display_name": "", @@ -1054,7 +664,7 @@ }, "dragging": false, "height": 513, - "id": "note-iNLPA", + "id": "note-ifPGq", "position": { "x": 244.92297036777086, "y": 340.99805740871204 @@ -1064,19 +674,23 @@ "y": 340.99805740871204 }, "resizing": false, - "selected": true, + "selected": false, "style": { "height": 513, "width": 567 }, "type": "noteNode", - "width": 567 + "width": 567, + "measured": { + "width": 328, + "height": 513 + } }, { "data": { "description": "Transforms LLM responses into **structured data formats**. Ideal for extracting specific information or creating consistent outputs.", "display_name": "Structured Output", - "id": "StructuredOutputComponent-421WY", + "id": "StructuredOutputComponent-Fk5AM", "node": { "base_classes": [ "Data" @@ -1336,10 +950,10 @@ }, "dragging": false, "height": 541, - "id": "StructuredOutputComponent-421WY", + "id": "StructuredOutputComponent-Fk5AM", "position": { - "x": 1770.7096106546323, - "y": 518.8182475390113 + "x": 1716.7237308033855, + "y": 459.2476214962564 }, "positionAbsolute": { "x": 1770.7096106546323, @@ -1347,13 +961,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 541 + } }, { "data": { "description": "Generates text using OpenAI LLMs.", "display_name": "OpenAI", - "id": "OpenAIModel-1WzgM", + "id": "OpenAIModel-qEjqV", "node": { "base_classes": [ "LanguageModel", @@ -1384,7 +1002,7 @@ "frozen": false, "icon": "OpenAI", "legacy": false, - "lf_version": "1.0.19.post2", + "lf_version": "1.1.1", "metadata": {}, "output_types": [], "outputs": [ @@ -1433,7 +1051,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -1648,10 +1266,10 @@ }, "dragging": false, "height": 543, - "id": "OpenAIModel-1WzgM", + "id": "OpenAIModel-qEjqV", "position": { - "x": 1631.501592565594, - "y": 1086.5741650125892 + "x": 1696.6021757625274, + "y": 1053.2300549755305 }, "positionAbsolute": { "x": 1631.501592565594, @@ -1659,11 +1277,15 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 543 + } }, { "data": { - "id": "ParseData-rO6Qs", + "id": "ParseData-zFzM6", "node": { "base_classes": [ "Message" @@ -1798,7 +1420,7 @@ }, "dragging": false, "height": 302, - "id": "ParseData-rO6Qs", + "id": "ParseData-zFzM6", "position": { "x": 2139.05558520377, "y": 780.6849187394922 @@ -1809,13 +1431,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 302 + } }, { "data": { "description": "Define the agent's instructions, then enter a task to complete using tools.", "display_name": "Agent", - "id": "Agent-QSS16", + "id": "Agent-axUVK", "node": { "base_classes": [ "Message" @@ -1858,7 +1484,7 @@ "frozen": false, "icon": "bot", "legacy": false, - "lf_version": "1.0.19.post2", + "lf_version": "1.1.1", "metadata": {}, "output_types": [], "outputs": [ @@ -1961,7 +1587,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -2374,18 +2000,22 @@ }, "dragging": false, "height": 650, - "id": "Agent-QSS16", + "id": "Agent-axUVK", "position": { "x": 1287.5681517817056, "y": 519.8701526087884 }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 650 + } }, { "data": { - "id": "note-uNkbX", + "id": "note-NrsCo", "node": { "description": "# 🔑 Tavily AI Search Needs API Key\n\nYou can get 1000 searches/month free [here](https://tavily.com/) ", "display_name": "", @@ -2398,10 +2028,10 @@ }, "dragging": false, "height": 325, - "id": "note-uNkbX", + "id": "note-NrsCo", "position": { - "x": 921.6062384772317, - "y": 642.1140062279873 + "x": 878.7898510090017, + "y": 640.2524241641511 }, "positionAbsolute": { "x": 921.6062384772317, @@ -2409,13 +2039,512 @@ }, "selected": false, "type": "noteNode", - "width": 325 + "width": 325, + "measured": { + "width": 328, + "height": 325 + } + }, + { + "id": "TavilySearchComponent-J0fu0", + "type": "genericNode", + "position": { + "x": 875.7686789989679, + "y": 798.478848045035 + }, + "data": { + "node": { + "template": { + "_type": "Component", + "api_key": { + "load_from_db": false, + "required": true, + "placeholder": "", + "show": true, + "name": "api_key", + "value": "", + "display_name": "Tavily API Key", + "advanced": false, + "input_types": [ + "Message" + ], + "dynamic": false, + "info": "Your Tavily API Key.", + "title_case": false, + "password": true, + "type": "str", + "_input_type": "SecretStrInput" + }, + "code": { + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "import httpx\nfrom loguru import logger\n\nfrom langflow.custom import Component\nfrom langflow.helpers.data import data_to_text\nfrom langflow.io import BoolInput, DropdownInput, IntInput, MessageTextInput, Output, SecretStrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass TavilySearchComponent(Component):\n display_name = \"Tavily AI Search\"\n description = \"\"\"**Tavily AI** is a search engine optimized for LLMs and RAG, \\\n aimed at efficient, quick, and persistent search results.\"\"\"\n icon = \"TavilyIcon\"\n\n inputs = [\n SecretStrInput(\n name=\"api_key\",\n display_name=\"Tavily API Key\",\n required=True,\n info=\"Your Tavily API Key.\",\n ),\n MessageTextInput(\n name=\"query\",\n display_name=\"Search Query\",\n info=\"The search query you want to execute with Tavily.\",\n tool_mode=True,\n ),\n DropdownInput(\n name=\"search_depth\",\n display_name=\"Search Depth\",\n info=\"The depth of the search.\",\n options=[\"basic\", \"advanced\"],\n value=\"advanced\",\n advanced=True,\n ),\n DropdownInput(\n name=\"topic\",\n display_name=\"Search Topic\",\n info=\"The category of the search.\",\n options=[\"general\", \"news\"],\n value=\"general\",\n advanced=True,\n ),\n IntInput(\n name=\"max_results\",\n display_name=\"Max Results\",\n info=\"The maximum number of search results to return.\",\n value=5,\n advanced=True,\n ),\n BoolInput(\n name=\"include_images\",\n display_name=\"Include Images\",\n info=\"Include a list of query-related images in the response.\",\n value=True,\n advanced=True,\n ),\n BoolInput(\n name=\"include_answer\",\n display_name=\"Include Answer\",\n info=\"Include a short answer to original query.\",\n value=True,\n advanced=True,\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"fetch_content\"),\n Output(display_name=\"Text\", name=\"text\", method=\"fetch_content_text\"),\n ]\n\n def fetch_content(self) -> list[Data]:\n try:\n url = \"https://api.tavily.com/search\"\n headers = {\n \"content-type\": \"application/json\",\n \"accept\": \"application/json\",\n }\n payload = {\n \"api_key\": self.api_key,\n \"query\": self.query,\n \"search_depth\": self.search_depth,\n \"topic\": self.topic,\n \"max_results\": self.max_results,\n \"include_images\": self.include_images,\n \"include_answer\": self.include_answer,\n }\n\n with httpx.Client() as client:\n response = client.post(url, json=payload, headers=headers)\n\n response.raise_for_status()\n search_results = response.json()\n\n data_results = []\n\n if self.include_answer and search_results.get(\"answer\"):\n data_results.append(Data(text=search_results[\"answer\"]))\n\n for result in search_results.get(\"results\", []):\n content = result.get(\"content\", \"\")\n data_results.append(\n Data(\n text=content,\n data={\n \"title\": result.get(\"title\"),\n \"url\": result.get(\"url\"),\n \"content\": content,\n \"score\": result.get(\"score\"),\n },\n )\n )\n\n if self.include_images and search_results.get(\"images\"):\n data_results.append(Data(text=\"Images found\", data={\"images\": search_results[\"images\"]}))\n except httpx.HTTPStatusError as exc:\n error_message = f\"HTTP error occurred: {exc.response.status_code} - {exc.response.text}\"\n logger.error(error_message)\n return [Data(text=error_message, data={\"error\": error_message})]\n except httpx.RequestError as exc:\n error_message = f\"Request error occurred: {exc}\"\n logger.error(error_message)\n return [Data(text=error_message, data={\"error\": error_message})]\n except ValueError as exc:\n error_message = f\"Invalid response format: {exc}\"\n logger.error(error_message)\n return [Data(text=error_message, data={\"error\": error_message})]\n else:\n self.status = data_results\n return data_results\n\n def fetch_content_text(self) -> Message:\n data = self.fetch_content()\n result_string = data_to_text(\"{text}\", data)\n self.status = result_string\n return Message(text=result_string)\n", + "fileTypes": [], + "file_path": "", + "password": false, + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false + }, + "include_answer": { + "tool_mode": false, + "trace_as_metadata": true, + "list": false, + "list_add_label": "Add More", + "required": false, + "placeholder": "", + "show": true, + "name": "include_answer", + "value": true, + "display_name": "Include Answer", + "advanced": true, + "dynamic": false, + "info": "Include a short answer to original query.", + "title_case": false, + "type": "bool", + "_input_type": "BoolInput" + }, + "include_images": { + "tool_mode": false, + "trace_as_metadata": true, + "list": false, + "list_add_label": "Add More", + "required": false, + "placeholder": "", + "show": true, + "name": "include_images", + "value": true, + "display_name": "Include Images", + "advanced": true, + "dynamic": false, + "info": "Include a list of query-related images in the response.", + "title_case": false, + "type": "bool", + "_input_type": "BoolInput" + }, + "max_results": { + "tool_mode": false, + "trace_as_metadata": true, + "list": false, + "list_add_label": "Add More", + "required": false, + "placeholder": "", + "show": true, + "name": "max_results", + "value": 5, + "display_name": "Max Results", + "advanced": true, + "dynamic": false, + "info": "The maximum number of search results to return.", + "title_case": false, + "type": "int", + "_input_type": "IntInput" + }, + "query": { + "tool_mode": true, + "trace_as_input": true, + "trace_as_metadata": true, + "load_from_db": false, + "list": false, + "list_add_label": "Add More", + "required": false, + "placeholder": "", + "show": true, + "name": "query", + "value": "", + "display_name": "Search Query", + "advanced": false, + "input_types": [ + "Message" + ], + "dynamic": false, + "info": "The search query you want to execute with Tavily.", + "title_case": false, + "type": "str", + "_input_type": "MessageTextInput" + }, + "search_depth": { + "tool_mode": false, + "trace_as_metadata": true, + "options": [ + "basic", + "advanced" + ], + "combobox": false, + "required": false, + "placeholder": "", + "show": true, + "name": "search_depth", + "value": "advanced", + "display_name": "Search Depth", + "advanced": true, + "dynamic": false, + "info": "The depth of the search.", + "title_case": false, + "type": "str", + "_input_type": "DropdownInput" + }, + "topic": { + "tool_mode": false, + "trace_as_metadata": true, + "options": [ + "general", + "news" + ], + "combobox": false, + "required": false, + "placeholder": "", + "show": true, + "name": "topic", + "value": "general", + "display_name": "Search Topic", + "advanced": true, + "dynamic": false, + "info": "The category of the search.", + "title_case": false, + "type": "str", + "_input_type": "DropdownInput" + }, + "tools_metadata": { + "tool_mode": false, + "is_list": true, + "list_add_label": "Add More", + "table_schema": { + "columns": [ + { + "name": "name", + "display_name": "Tool Name", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Specify the name of the tool.", + "disable_edit": false, + "edit_mode": "inline", + "formatter": "text" + }, + { + "name": "description", + "display_name": "Tool Description", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Describe the purpose of the tool.", + "disable_edit": false, + "edit_mode": "popover", + "formatter": "text" + }, + { + "name": "tags", + "display_name": "Tool Identifiers", + "sortable": false, + "filterable": false, + "type": "text", + "description": "The default identifiers for the tools and cannot be changed.", + "disable_edit": true, + "edit_mode": "inline", + "formatter": "text" + }, + { + "name": "commands", + "display_name": "Commands", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Add commands to the tool. These commands will be used to run the tool. Start all commands with a `/`. You can add multiple commands separated by a comma.\nExample: `/command1`, `/command2`, `/command3`", + "disable_edit": false, + "edit_mode": "inline", + "formatter": "text" + } + ] + }, + "trigger_text": "", + "trigger_icon": "Hammer", + "table_icon": "Hammer", + "table_options": { + "block_add": true, + "block_delete": true, + "block_edit": true, + "block_sort": true, + "block_filter": true, + "block_hide": true, + "block_select": true, + "hide_options": true, + "field_parsers": { + "name": [ + "snake_case", + "no_blank" + ], + "commands": "commands" + }, + "description": "Modify tool names and descriptions to help agents understand when to use each tool." + }, + "trace_as_metadata": true, + "required": false, + "placeholder": "", + "show": true, + "name": "tools_metadata", + "value": [ + { + "name": "None-fetch_content", + "description": "fetch_content(api_key: Message) - **Tavily AI** is a search engine optimized for LLMs and RAG, aimed at efficient, quick, and persistent search results.", + "tags": [ + "None-fetch_content" + ] + }, + { + "name": "None-fetch_content_text", + "description": "fetch_content_text(api_key: Message) - **Tavily AI** is a search engine optimized for LLMs and RAG, aimed at efficient, quick, and persistent search results.", + "tags": [ + "None-fetch_content_text" + ] + } + ], + "display_name": "Edit tools", + "advanced": false, + "dynamic": false, + "info": "", + "real_time_refresh": true, + "title_case": false, + "type": "table", + "_input_type": "TableInput" + } + }, + "description": "**Tavily AI** is a search engine optimized for LLMs and RAG, aimed at efficient, quick, and persistent search results.", + "icon": "TavilyIcon", + "base_classes": [ + "Data", + "Message" + ], + "display_name": "Tavily AI Search", + "documentation": "", + "minimized": false, + "custom_fields": {}, + "output_types": [], + "pinned": false, + "conditional_paths": [], + "frozen": false, + "outputs": [ + { + "types": [ + "Tool" + ], + "selected": "Tool", + "name": "component_as_tool", + "hidden": null, + "display_name": "Toolset", + "method": "to_toolkit", + "value": "__UNDEFINED__", + "cache": true, + "required_inputs": null + } + ], + "field_order": [ + "api_key", + "query", + "search_depth", + "topic", + "max_results", + "include_images", + "include_answer" + ], + "beta": false, + "legacy": false, + "edited": false, + "metadata": {}, + "category": "tools", + "key": "TavilySearchComponent", + "score": 0.0075846556637275304 + }, + "showNode": true, + "type": "TavilySearchComponent", + "id": "TavilySearchComponent-J0fu0" + }, + "selected": true, + "measured": { + "width": 360, + "height": 489 + }, + "dragging": false + } + ], + "edges": [ + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "OpenAIModel", + "id": "OpenAIModel-qEjqV", + "name": "model_output", + "output_types": [ + "LanguageModel" + ] + }, + "targetHandle": { + "fieldName": "llm", + "id": "StructuredOutputComponent-Fk5AM", + "inputTypes": [ + "LanguageModel" + ], + "type": "other" + } + }, + "id": "reactflow__edge-OpenAIModel-qEjqV{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-qEjqVœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutputComponent-Fk5AM{œfieldNameœ:œllmœ,œidœ:œStructuredOutputComponent-Fk5AMœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", + "selected": false, + "source": "OpenAIModel-qEjqV", + "sourceHandle": "{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-qEjqVœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}", + "target": "StructuredOutputComponent-Fk5AM", + "targetHandle": "{œfieldNameœ:œllmœ,œidœ:œStructuredOutputComponent-Fk5AMœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "StructuredOutputComponent", + "id": "StructuredOutputComponent-Fk5AM", + "name": "structured_output", + "output_types": [ + "Data" + ] + }, + "targetHandle": { + "fieldName": "data", + "id": "ParseData-zFzM6", + "inputTypes": [ + "Data" + ], + "type": "other" + } + }, + "id": "reactflow__edge-StructuredOutputComponent-Fk5AM{œdataTypeœ:œStructuredOutputComponentœ,œidœ:œStructuredOutputComponent-Fk5AMœ,œnameœ:œstructured_outputœ,œoutput_typesœ:[œDataœ]}-ParseData-zFzM6{œfieldNameœ:œdataœ,œidœ:œParseData-zFzM6œ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", + "selected": false, + "source": "StructuredOutputComponent-Fk5AM", + "sourceHandle": "{œdataTypeœ:œStructuredOutputComponentœ,œidœ:œStructuredOutputComponent-Fk5AMœ,œnameœ:œstructured_outputœ,œoutput_typesœ:[œDataœ]}", + "target": "ParseData-zFzM6", + "targetHandle": "{œfieldNameœ:œdataœ,œidœ:œParseData-zFzM6œ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "ParseData", + "id": "ParseData-zFzM6", + "name": "text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-NJfzg", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-ParseData-zFzM6{œdataTypeœ:œParseDataœ,œidœ:œParseData-zFzM6œ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-NJfzg{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-NJfzgœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "ParseData-zFzM6", + "sourceHandle": "{œdataTypeœ:œParseDataœ,œidœ:œParseData-zFzM6œ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}", + "target": "ChatOutput-NJfzg", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-NJfzgœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "ChatInput", + "id": "ChatInput-N6esY", + "name": "message", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "Agent-axUVK", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-ChatInput-N6esY{œdataTypeœ:œChatInputœ,œidœ:œChatInput-N6esYœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Agent-axUVK{œfieldNameœ:œinput_valueœ,œidœ:œAgent-axUVKœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "ChatInput-N6esY", + "sourceHandle": "{œdataTypeœ:œChatInputœ,œidœ:œChatInput-N6esYœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}", + "target": "Agent-axUVK", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAgent-axUVKœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "Agent", + "id": "Agent-axUVK", + "name": "response", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "StructuredOutputComponent-Fk5AM", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-Agent-axUVK{œdataTypeœ:œAgentœ,œidœ:œAgent-axUVKœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-StructuredOutputComponent-Fk5AM{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutputComponent-Fk5AMœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "Agent-axUVK", + "sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-axUVKœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}", + "target": "StructuredOutputComponent-Fk5AM", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutputComponent-Fk5AMœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" + }, + { + "source": "TavilySearchComponent-J0fu0", + "sourceHandle": "{œdataTypeœ:œTavilySearchComponentœ,œidœ:œTavilySearchComponent-J0fu0œ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}", + "target": "Agent-axUVK", + "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgent-axUVKœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", + "data": { + "targetHandle": { + "fieldName": "tools", + "id": "Agent-axUVK", + "inputTypes": [ + "Tool" + ], + "type": "other" + }, + "sourceHandle": { + "dataType": "TavilySearchComponent", + "id": "TavilySearchComponent-J0fu0", + "name": "component_as_tool", + "output_types": [ + "Tool" + ] + } + }, + "id": "xy-edge__TavilySearchComponent-J0fu0{œdataTypeœ:œTavilySearchComponentœ,œidœ:œTavilySearchComponent-J0fu0œ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}-Agent-axUVK{œfieldNameœ:œtoolsœ,œidœ:œAgent-axUVKœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" } ], "viewport": { - "x": -56.31509213451284, - "y": 23.784977680322072, - "zoom": 0.5068195797812174 + "x": -56.57567835815098, + "y": -85.58742561611257, + "zoom": 0.5411592744108725 } }, "description": "Researches companies, extracts key business data, and presents structured information for efficient analysis. ", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json b/src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json index c316b4968..1eacdc033 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json @@ -1,94 +1,11 @@ { "data": { - "edges": [ - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "CalculatorTool", - "id": "CalculatorTool-DF8xQ", - "name": "api_build_tool", - "output_types": [ - "Tool" - ] - }, - "targetHandle": { - "fieldName": "tools", - "id": "Agent-5e01q", - "inputTypes": [ - "Tool" - ], - "type": "other" - } - }, - "id": "reactflow__edge-CalculatorTool-DF8xQ{œdataTypeœ:œCalculatorToolœ,œidœ:œCalculatorTool-DF8xQœ,œnameœ:œapi_build_toolœ,œoutput_typesœ:[œToolœ]}-Agent-5e01q{œfieldNameœ:œtoolsœ,œidœ:œAgent-5e01qœ,œinputTypesœ:[œToolœ,œBaseToolœ,œStructuredToolœ],œtypeœ:œotherœ}", - "source": "CalculatorTool-DF8xQ", - "sourceHandle": "{œdataTypeœ: œCalculatorToolœ, œidœ: œCalculatorTool-DF8xQœ, œnameœ: œapi_build_toolœ, œoutput_typesœ: [œToolœ]}", - "target": "Agent-5e01q", - "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œAgent-5e01qœ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "Agent", - "id": "Agent-5e01q", - "name": "response", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "ChatOutput-s1eJK", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-Agent-5e01q{œdataTypeœ:œAgentœ,œidœ:œAgent-5e01qœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-s1eJK{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-s1eJKœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "source": "Agent-5e01q", - "sourceHandle": "{œdataTypeœ: œAgentœ, œidœ: œAgent-5e01qœ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-s1eJK", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-s1eJKœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "Prompt", - "id": "Prompt-KkcsZ", - "name": "prompt", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "Agent-5e01q", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-Prompt-KkcsZ{œdataTypeœ:œPromptœ,œidœ:œPrompt-KkcsZœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-Agent-5e01q{œfieldNameœ:œinput_valueœ,œidœ:œAgent-5e01qœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "source": "Prompt-KkcsZ", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-KkcsZœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "Agent-5e01q", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAgent-5e01qœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - } - ], "nodes": [ { "data": { "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", - "id": "Prompt-KkcsZ", + "id": "Prompt-nzVmM", "node": { "base_classes": [ "Message" @@ -313,7 +230,7 @@ }, "dragging": false, "height": 693, - "id": "Prompt-KkcsZ", + "id": "Prompt-nzVmM", "position": { "x": 1349.861745038984, "y": 347.90475109976467 @@ -324,13 +241,17 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 693 + } }, { "data": { "description": "Display a chat message in the Playground.", "display_name": "Chat Output", - "id": "ChatOutput-s1eJK", + "id": "ChatOutput-60t7m", "node": { "base_classes": [ "Message" @@ -590,7 +511,7 @@ }, "dragging": false, "height": 234, - "id": "ChatOutput-s1eJK", + "id": "ChatOutput-60t7m", "position": { "x": 2240.3625274769397, "y": 355.16302699218204 @@ -601,11 +522,15 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 234 + } }, { "data": { - "id": "note-H6OpG", + "id": "note-BnQHz", "node": { "description": "# SaaS Pricing Calculator\n\nWelcome to the SaaS Pricing Calculator! This flow helps you determine the optimal monthly subscription price for your software service.\n\n## Instructions\n\n1. Prepare Your Data\n - Gather information on monthly infrastructure costs\n - Calculate customer support expenses\n - Estimate continuous development costs\n - Decide on your desired profit margin\n - Determine the estimated number of subscribers\n\n2. Input Values\n - Enter the gathered data into the respective fields in the Prompt node\n - Double-check the accuracy of your inputs\n\n3. Run the Flow\n - Click the \"Run\" button to start the calculation process\n - The flow will use Chain-of-Thought prompting to guide the AI through the steps\n\n4. Review the Results\n - Examine the output in the Chat Output node\n - The result will show a breakdown of costs and the final subscription price\n\n5. Adjust and Refine\n - If needed, modify your inputs to explore different pricing scenarios\n - Re-run the flow to see how changes affect the final price\n\nRemember: Regularly update your costs and subscriber estimates to keep your pricing model accurate and competitive! 💼📊", "display_name": "", @@ -616,7 +541,7 @@ }, "dragging": false, "height": 800, - "id": "note-H6OpG", + "id": "note-BnQHz", "position": { "x": 689.7659055360411, "y": 68.95847391680593 @@ -632,13 +557,17 @@ "width": 600 }, "type": "noteNode", - "width": 600 + "width": 600, + "measured": { + "width": 328, + "height": 800 + } }, { "data": { "description": "Define the agent's instructions, then enter a task to complete using tools.", "display_name": "Agent", - "id": "Agent-5e01q", + "id": "Agent-HoULP", "node": { "base_classes": [ "Message" @@ -784,7 +713,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -1197,7 +1126,7 @@ }, "dragging": false, "height": 650, - "id": "Agent-5e01q", + "id": "Agent-HoULP", "position": { "x": 1819.2633856623966, "y": 138.32023808479687 @@ -1208,126 +1137,297 @@ }, "selected": false, "type": "genericNode", - "width": 320 + "width": 320, + "measured": { + "width": 360, + "height": 650 + } }, { + "id": "CalculatorComponent-A0PBx", + "type": "genericNode", + "position": { + "x": 1350.9477037257504, + "y": -45.351578570289234 + }, "data": { - "id": "CalculatorTool-DF8xQ", "node": { - "base_classes": [ - "Data", - "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", - "legacy": false, - "lf_version": "1.0.19.post2", - "metadata": {}, - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Data", - "method": "run_model", - "name": "api_run_model", - "required_inputs": [], - "selected": "Data", - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Tool", - "method": "build_tool", - "name": "api_build_tool", - "required_inputs": [], - "selected": "Tool", - "types": [ - "Tool" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, "template": { "_type": "Component", "code": { - "advanced": true, - "dynamic": true, + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "import ast\nimport operator\nfrom collections.abc import Callable\n\nfrom langflow.custom import Component\nfrom langflow.inputs import MessageTextInput\nfrom langflow.io import Output\nfrom langflow.schema import Data\n\n\nclass CalculatorComponent(Component):\n display_name = \"Calculator\"\n description = \"Perform basic arithmetic operations on a given expression.\"\n icon = \"calculator\"\n\n # Cache operators dictionary as a class variable\n OPERATORS: dict[type[ast.operator], Callable] = {\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 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 tool_mode=True,\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"result\", type_=Data, method=\"evaluate_expression\"),\n ]\n\n def _eval_expr(self, node: ast.AST) -> float:\n \"\"\"Evaluate an AST node recursively.\"\"\"\n if isinstance(node, ast.Constant):\n if isinstance(node.value, int | float):\n return float(node.value)\n error_msg = f\"Unsupported constant type: {type(node.value).__name__}\"\n raise TypeError(error_msg)\n if isinstance(node, ast.Num): # For backwards compatibility\n if isinstance(node.n, int | float):\n return float(node.n)\n error_msg = f\"Unsupported number type: {type(node.n).__name__}\"\n raise TypeError(error_msg)\n\n if isinstance(node, ast.BinOp):\n op_type = type(node.op)\n if op_type not in self.OPERATORS:\n error_msg = f\"Unsupported binary operator: {op_type.__name__}\"\n raise TypeError(error_msg)\n\n left = self._eval_expr(node.left)\n right = self._eval_expr(node.right)\n return self.OPERATORS[op_type](left, right)\n\n error_msg = f\"Unsupported operation or expression type: {type(node).__name__}\"\n raise TypeError(error_msg)\n\n def evaluate_expression(self) -> Data:\n \"\"\"Evaluate the mathematical expression and return the result.\"\"\"\n try:\n tree = ast.parse(self.expression, mode=\"eval\")\n result = self._eval_expr(tree.body)\n\n formatted_result = f\"{float(result):.6f}\".rstrip(\"0\").rstrip(\".\")\n self.log(f\"Calculation result: {formatted_result}\")\n\n self.status = formatted_result\n return Data(data={\"result\": formatted_result})\n\n except ZeroDivisionError:\n error_message = \"Error: Division by zero\"\n self.status = error_message\n return Data(data={\"error\": error_message, \"input\": self.expression})\n\n except (SyntaxError, TypeError, KeyError, ValueError, AttributeError, OverflowError) as e:\n error_message = f\"Invalid expression: {e!s}\"\n self.status = error_message\n return Data(data={\"error\": error_message, \"input\": self.expression})\n\n def build(self):\n \"\"\"Return the main evaluation function.\"\"\"\n return self.evaluate_expression\n", "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 langchain_core.tools import ToolException\nfrom loguru import logger\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._eval_expr_with_error,\n args_schema=self.CalculatorToolSchema,\n )\n\n def _eval_expr(self, node):\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 if isinstance(node, ast.Num):\n return node.n\n if isinstance(node, ast.BinOp):\n return operators[type(node.op)](self._eval_expr(node.left), self._eval_expr(node.right))\n if isinstance(node, ast.UnaryOp):\n return operators[type(node.op)](self._eval_expr(node.operand))\n if isinstance(node, ast.Call):\n msg = (\n \"Function calls like sqrt(), sin(), cos() etc. are not supported. \"\n \"Only basic arithmetic operations (+, -, *, /, **) are allowed.\"\n )\n raise TypeError(msg)\n msg = f\"Unsupported operation or expression type: {type(node).__name__}\"\n raise TypeError(msg)\n\n def _eval_expr_with_error(self, expression: str) -> list[Data]:\n try:\n return self._evaluate_expression(expression)\n except Exception as e:\n raise ToolException(str(e)) from e\n\n def _evaluate_expression(self, expression: str) -> list[Data]:\n try:\n # Parse the expression and evaluate it\n tree = ast.parse(expression, mode=\"eval\")\n result = self._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: {e}\"\n self.status = error_message\n return [Data(data={\"error\": error_message, \"input\": expression})]\n except ZeroDivisionError:\n error_message = \"Error: Division by zero\"\n self.status = error_message\n return [Data(data={\"error\": error_message, \"input\": expression})]\n except Exception as e: # noqa: BLE001\n logger.opt(exception=True).debug(\"Error evaluating expression\")\n error_message = f\"Error: {e}\"\n self.status = error_message\n return [Data(data={\"error\": error_message, \"input\": expression})]\n" + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false }, "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, "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, + "load_from_db": false, + "list": false, + "list_add_label": "Add More", + "required": false, + "placeholder": "", + "show": true, + "name": "expression", + "value": "", + "display_name": "Expression", + "advanced": false, + "input_types": [ + "Message" + ], + "dynamic": false, + "info": "The arithmetic expression to evaluate (e.g., '4*4*(33/22)+12-20').", + "title_case": false, "type": "str", - "value": "" + "_input_type": "MessageTextInput" + }, + "tools_metadata": { + "tool_mode": false, + "is_list": true, + "list_add_label": "Add More", + "table_schema": { + "columns": [ + { + "name": "name", + "display_name": "Tool Name", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Specify the name of the tool.", + "disable_edit": false, + "edit_mode": "inline", + "formatter": "text" + }, + { + "name": "description", + "display_name": "Tool Description", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Describe the purpose of the tool.", + "disable_edit": false, + "edit_mode": "popover", + "formatter": "text" + }, + { + "name": "tags", + "display_name": "Tool Identifiers", + "sortable": false, + "filterable": false, + "type": "text", + "description": "The default identifiers for the tools and cannot be changed.", + "disable_edit": true, + "edit_mode": "inline", + "formatter": "text" + }, + { + "name": "commands", + "display_name": "Commands", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Add commands to the tool. These commands will be used to run the tool. Start all commands with a `/`. You can add multiple commands separated by a comma.\nExample: `/command1`, `/command2`, `/command3`", + "disable_edit": false, + "edit_mode": "inline", + "formatter": "text" + } + ] + }, + "trigger_text": "", + "trigger_icon": "Hammer", + "table_icon": "Hammer", + "table_options": { + "block_add": true, + "block_delete": true, + "block_edit": true, + "block_sort": true, + "block_filter": true, + "block_hide": true, + "block_select": true, + "hide_options": true, + "field_parsers": { + "name": [ + "snake_case", + "no_blank" + ], + "commands": "commands" + }, + "description": "Modify tool names and descriptions to help agents understand when to use each tool." + }, + "trace_as_metadata": true, + "required": false, + "placeholder": "", + "show": true, + "name": "tools_metadata", + "value": [ + { + "name": "None-evaluate_expression", + "description": "evaluate_expression() - Perform basic arithmetic operations on a given expression.", + "tags": [ + "None-evaluate_expression" + ] + } + ], + "display_name": "Edit tools", + "advanced": false, + "dynamic": false, + "info": "", + "real_time_refresh": true, + "title_case": false, + "type": "table", + "_input_type": "TableInput" } }, - "tool_mode": false + "description": "Perform basic arithmetic operations on a given expression.", + "icon": "calculator", + "base_classes": [ + "Data" + ], + "display_name": "Calculator", + "documentation": "", + "minimized": false, + "custom_fields": {}, + "output_types": [], + "pinned": false, + "conditional_paths": [], + "frozen": false, + "outputs": [ + { + "types": [ + "Tool" + ], + "selected": "Tool", + "name": "component_as_tool", + "hidden": null, + "display_name": "Toolset", + "method": "to_toolkit", + "value": "__UNDEFINED__", + "cache": true, + "required_inputs": null + } + ], + "field_order": [ + "expression" + ], + "beta": false, + "legacy": false, + "edited": false, + "metadata": {}, + "category": "tools", + "key": "CalculatorComponent", + "score": 0.001 }, - "type": "CalculatorTool" + "showNode": true, + "type": "CalculatorComponent", + "id": "CalculatorComponent-A0PBx" }, - "dragging": false, - "height": 167, - "id": "CalculatorTool-DF8xQ", - "position": { - "x": 1347.154214046272, - "y": 28.770424745017564 + "selected": true, + "measured": { + "width": 360, + "height": 374 }, - "positionAbsolute": { - "x": 1347.154214046272, - "y": 28.770424745017564 + "dragging": false + } + ], + "edges": [ + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "Agent", + "id": "Agent-HoULP", + "name": "response", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-60t7m", + "inputTypes": [ + "Message" + ], + "type": "str" + } }, - "selected": false, - "type": "genericNode", - "width": 320 + "id": "reactflow__edge-Agent-HoULP{œdataTypeœ:œAgentœ,œidœ:œAgent-HoULPœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-60t7m{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-60t7mœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "source": "Agent-HoULP", + "sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-HoULPœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}", + "target": "ChatOutput-60t7m", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-60t7mœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "Prompt", + "id": "Prompt-nzVmM", + "name": "prompt", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "Agent-HoULP", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-Prompt-nzVmM{œdataTypeœ:œPromptœ,œidœ:œPrompt-nzVmMœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-Agent-HoULP{œfieldNameœ:œinput_valueœ,œidœ:œAgent-HoULPœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "source": "Prompt-nzVmM", + "sourceHandle": "{œdataTypeœ:œPromptœ,œidœ:œPrompt-nzVmMœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}", + "target": "Agent-HoULP", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAgent-HoULPœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}" + }, + { + "source": "CalculatorComponent-A0PBx", + "sourceHandle": "{œdataTypeœ:œCalculatorComponentœ,œidœ:œCalculatorComponent-A0PBxœ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}", + "target": "Agent-HoULP", + "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgent-HoULPœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", + "data": { + "targetHandle": { + "fieldName": "tools", + "id": "Agent-HoULP", + "inputTypes": [ + "Tool" + ], + "type": "other" + }, + "sourceHandle": { + "dataType": "CalculatorComponent", + "id": "CalculatorComponent-A0PBx", + "name": "component_as_tool", + "output_types": [ + "Tool" + ] + } + }, + "id": "xy-edge__CalculatorComponent-A0PBx{œdataTypeœ:œCalculatorComponentœ,œidœ:œCalculatorComponent-A0PBxœ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}-Agent-HoULP{œfieldNameœ:œtoolsœ,œidœ:œAgent-HoULPœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}" } ], "viewport": { - "x": -251.17743782763955, - "y": 134.52045967838717, - "zoom": 0.6368650431844803 + "x": -453.80822100847854, + "y": 40.05341665740133, + "zoom": 0.7636833920540887 } }, "description": "Calculate SaaS subscription price based on costs, profit margin, and subscribers using step-by-step method and Chain-of-Thought prompting. ", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json index a9850b934..9cfc0eb66 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json @@ -1,117 +1,11 @@ { "data": { - "edges": [ - { - "data": { - "sourceHandle": { - "dataType": "ChatInput", - "id": "ChatInput-ilDxB", - "name": "message", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "Agent-WQiI8", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ChatInput-ilDxB{œdataTypeœ:œChatInputœ,œidœ:œChatInput-ilDxBœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Agent-WQiI8{œfieldNameœ:œinput_valueœ,œidœ:œAgent-WQiI8œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ChatInput-ilDxB", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-ilDxBœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "Agent-WQiI8", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAgent-WQiI8œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "data": { - "sourceHandle": { - "dataType": "Agent", - "id": "Agent-WQiI8", - "name": "response", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "ChatOutput-8jO4X", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-Agent-WQiI8{œdataTypeœ:œAgentœ,œidœ:œAgent-WQiI8œ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-8jO4X{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-8jO4Xœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "Agent-WQiI8", - "sourceHandle": "{œdataTypeœ: œAgentœ, œidœ: œAgent-WQiI8œ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-8jO4X", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-8jO4Xœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "data": { - "sourceHandle": { - "dataType": "URL", - "id": "URL-mRzJq", - "name": "component_as_tool", - "output_types": [ - "Tool" - ] - }, - "targetHandle": { - "fieldName": "tools", - "id": "Agent-WQiI8", - "inputTypes": [ - "Tool" - ], - "type": "other" - } - }, - "id": "reactflow__edge-URL-mRzJq{œdataTypeœ:œURLœ,œidœ:œURL-mRzJqœ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}-Agent-WQiI8{œfieldNameœ:œtoolsœ,œidœ:œAgent-WQiI8œ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", - "selected": false, - "source": "URL-mRzJq", - "sourceHandle": "{œdataTypeœ: œURLœ, œidœ: œURL-mRzJqœ, œnameœ: œcomponent_as_toolœ, œoutput_typesœ: [œToolœ]}", - "target": "Agent-WQiI8", - "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œAgent-WQiI8œ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}" - }, - { - "data": { - "sourceHandle": { - "dataType": "CalculatorTool", - "id": "CalculatorTool-d6fIp", - "name": "api_build_tool", - "output_types": [ - "Tool" - ] - }, - "targetHandle": { - "fieldName": "tools", - "id": "Agent-WQiI8", - "inputTypes": [ - "Tool" - ], - "type": "other" - } - }, - "id": "reactflow__edge-CalculatorTool-d6fIp{œdataTypeœ:œCalculatorToolœ,œidœ:œCalculatorTool-d6fIpœ,œnameœ:œapi_build_toolœ,œoutput_typesœ:[œToolœ]}-Agent-WQiI8{œfieldNameœ:œtoolsœ,œidœ:œAgent-WQiI8œ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", - "selected": false, - "source": "CalculatorTool-d6fIp", - "sourceHandle": "{œdataTypeœ: œCalculatorToolœ, œidœ: œCalculatorTool-d6fIpœ, œnameœ: œapi_build_toolœ, œoutput_typesœ: [œToolœ]}", - "target": "Agent-WQiI8", - "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œAgent-WQiI8œ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}" - } - ], "nodes": [ { "data": { "description": "Define the agent's instructions, then enter a task to complete using tools.", "display_name": "Agent", - "id": "Agent-WQiI8", + "id": "Agent-rl4Nb", "node": { "base_classes": [ "Message" @@ -154,7 +48,7 @@ "frozen": false, "icon": "bot", "legacy": false, - "lf_version": "1.1.0.dev4", + "lf_version": "1.1.1", "metadata": {}, "output_types": [], "outputs": [ @@ -249,7 +143,7 @@ "input_types": [ "Message" ], - "load_from_db": false, + "load_from_db": true, "name": "api_key", "password": true, "placeholder": "", @@ -668,21 +562,22 @@ }, "type": "Agent" }, - "id": "Agent-WQiI8", + "id": "Agent-rl4Nb", "measured": { - "height": 645, - "width": 320 + "height": 698, + "width": 360 }, "position": { "x": 1652.2479633316434, "y": 297.9085084144251 }, "selected": false, - "type": "genericNode" + "type": "genericNode", + "dragging": false }, { "data": { - "id": "ChatInput-ilDxB", + "id": "ChatInput-8EBqM", "node": { "base_classes": [ "Message" @@ -708,7 +603,7 @@ "frozen": false, "icon": "MessagesSquare", "legacy": false, - "lf_version": "1.1.0.dev4", + "lf_version": "1.1.1", "metadata": {}, "output_types": [], "outputs": [ @@ -960,23 +855,24 @@ }, "type": "ChatInput" }, - "id": "ChatInput-ilDxB", + "id": "ChatInput-8EBqM", "measured": { - "height": 233, - "width": 320 + "height": 257, + "width": 360 }, "position": { - "x": 1285.6593577254828, + "x": 1241.9566260691947, "y": 930.7462715570136 }, "selected": false, - "type": "genericNode" + "type": "genericNode", + "dragging": false }, { "data": { "description": "Display a chat message in the Playground.", "display_name": "Chat Output", - "id": "ChatOutput-8jO4X", + "id": "ChatOutput-f5pzU", "node": { "base_classes": [ "Message" @@ -1002,7 +898,7 @@ "frozen": false, "icon": "MessagesSquare", "legacy": false, - "lf_version": "1.1.0.dev4", + "lf_version": "1.1.1", "metadata": {}, "output_types": [], "outputs": [ @@ -1234,10 +1130,10 @@ }, "type": "ChatOutput" }, - "id": "ChatOutput-8jO4X", + "id": "ChatOutput-f5pzU", "measured": { - "height": 233, - "width": 320 + "height": 257, + "width": 360 }, "position": { "x": 2029.726227044409, @@ -1248,128 +1144,244 @@ }, { "data": { - "id": "URL-mRzJq", + "id": "URL-vRJK9", "node": { - "base_classes": [ - "Data", - "Message" - ], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "Fetch content from one or more URLs.", - "display_name": "URL", - "documentation": "", - "edited": false, - "field_order": [ - "urls", - "format" - ], - "frozen": false, - "icon": "layout-template", - "legacy": false, - "lf_version": "1.1.0.dev4", - "metadata": {}, - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Toolset", - "hidden": null, - "method": "to_toolkit", - "name": "component_as_tool", - "required_inputs": null, - "selected": "Tool", - "types": [ - "Tool" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, "template": { "_type": "Component", "code": { - "advanced": true, - "dynamic": true, + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "import re\n\nfrom langchain_community.document_loaders import AsyncHtmlLoader, WebBaseLoader\n\nfrom langflow.custom import Component\nfrom langflow.helpers.data import data_to_text\nfrom langflow.io import DropdownInput, MessageTextInput, Output\nfrom langflow.schema import Data\nfrom langflow.schema.dataframe import DataFrame\nfrom langflow.schema.message import Message\n\n\nclass URLComponent(Component):\n display_name = \"URL\"\n description = \"Load and retrive data from specified URLs.\"\n icon = \"layout-template\"\n name = \"URL\"\n\n inputs = [\n MessageTextInput(\n name=\"urls\",\n display_name=\"URLs\",\n is_list=True,\n tool_mode=True,\n placeholder=\"Enter a URL...\",\n list_add_label=\"Add URL\",\n ),\n DropdownInput(\n name=\"format\",\n display_name=\"Output Format\",\n info=\"Output Format. Use 'Text' to extract the text from the HTML or 'Raw HTML' for the raw HTML content.\",\n options=[\"Text\", \"Raw HTML\"],\n value=\"Text\",\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"fetch_content\"),\n Output(display_name=\"Text\", name=\"text\", method=\"fetch_content_text\"),\n Output(display_name=\"DataFrame\", name=\"dataframe\", method=\"as_dataframe\"),\n ]\n\n def ensure_url(self, string: str) -> str:\n \"\"\"Ensures the given string is a URL by adding 'http://' if it doesn't start with 'http://' or 'https://'.\n\n Raises an error if the string is not a valid URL.\n\n Parameters:\n string (str): The string to be checked and possibly modified.\n\n Returns:\n str: The modified string that is ensured to be a URL.\n\n Raises:\n ValueError: If the string is not a valid URL.\n \"\"\"\n if not string.startswith((\"http://\", \"https://\")):\n string = \"http://\" + string\n\n # Basic URL validation regex\n url_regex = re.compile(\n r\"^(https?:\\/\\/)?\" # optional protocol\n r\"(www\\.)?\" # optional www\n r\"([a-zA-Z0-9.-]+)\" # domain\n r\"(\\.[a-zA-Z]{2,})?\" # top-level domain\n r\"(:\\d+)?\" # optional port\n r\"(\\/[^\\s]*)?$\", # optional path\n re.IGNORECASE,\n )\n\n if not url_regex.match(string):\n msg = f\"Invalid URL: {string}\"\n raise ValueError(msg)\n\n return string\n\n def fetch_content(self) -> list[Data]:\n urls = [self.ensure_url(url.strip()) for url in self.urls if url.strip()]\n if self.format == \"Raw HTML\":\n loader = AsyncHtmlLoader(web_path=urls, encoding=\"utf-8\")\n else:\n loader = WebBaseLoader(web_paths=urls, encoding=\"utf-8\")\n docs = loader.load()\n data = [Data(text=doc.page_content, **doc.metadata) for doc in docs]\n self.status = data\n return data\n\n def fetch_content_text(self) -> Message:\n data = self.fetch_content()\n\n result_string = data_to_text(\"{text}\", data)\n self.status = result_string\n return Message(text=result_string)\n\n def as_dataframe(self) -> DataFrame:\n return DataFrame(self.fetch_content())\n", "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 re\n\nfrom langchain_community.document_loaders import AsyncHtmlLoader, WebBaseLoader\n\nfrom langflow.custom import Component\nfrom langflow.helpers.data import data_to_text\nfrom langflow.io import DropdownInput, MessageTextInput, Output\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass URLComponent(Component):\n display_name = \"URL\"\n description = \"Fetch content from one or more URLs.\"\n icon = \"layout-template\"\n name = \"URL\"\n\n inputs = [\n MessageTextInput(\n name=\"urls\",\n display_name=\"URLs\",\n info=\"Enter one or more URLs, by clicking the '+' button.\",\n is_list=True,\n tool_mode=True,\n ),\n DropdownInput(\n name=\"format\",\n display_name=\"Output Format\",\n info=\"Output Format. Use 'Text' to extract the text from the HTML or 'Raw HTML' for the raw HTML content.\",\n options=[\"Text\", \"Raw HTML\"],\n value=\"Text\",\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"data\", method=\"fetch_content\"),\n Output(display_name=\"Text\", name=\"text\", method=\"fetch_content_text\"),\n ]\n\n def ensure_url(self, string: str) -> str:\n \"\"\"Ensures the given string is a URL by adding 'http://' if it doesn't start with 'http://' or 'https://'.\n\n Raises an error if the string is not a valid URL.\n\n Parameters:\n string (str): The string to be checked and possibly modified.\n\n Returns:\n str: The modified string that is ensured to be a URL.\n\n Raises:\n ValueError: If the string is not a valid URL.\n \"\"\"\n if not string.startswith((\"http://\", \"https://\")):\n string = \"http://\" + string\n\n # Basic URL validation regex\n url_regex = re.compile(\n r\"^(https?:\\/\\/)?\" # optional protocol\n r\"(www\\.)?\" # optional www\n r\"([a-zA-Z0-9.-]+)\" # domain\n r\"(\\.[a-zA-Z]{2,})?\" # top-level domain\n r\"(:\\d+)?\" # optional port\n r\"(\\/[^\\s]*)?$\", # optional path\n re.IGNORECASE,\n )\n\n if not url_regex.match(string):\n msg = f\"Invalid URL: {string}\"\n raise ValueError(msg)\n\n return string\n\n def fetch_content(self) -> list[Data]:\n urls = [self.ensure_url(url.strip()) for url in self.urls if url.strip()]\n if self.format == \"Raw HTML\":\n loader = AsyncHtmlLoader(web_path=urls, encoding=\"utf-8\")\n else:\n loader = WebBaseLoader(web_paths=urls, encoding=\"utf-8\")\n docs = loader.load()\n data = [Data(text=doc.page_content, **doc.metadata) for doc in docs]\n self.status = data\n return data\n\n def fetch_content_text(self) -> Message:\n data = self.fetch_content()\n\n result_string = data_to_text(\"{text}\", data)\n self.status = result_string\n return Message(text=result_string)\n" + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false }, "format": { - "_input_type": "DropdownInput", - "advanced": false, - "combobox": false, - "display_name": "Output Format", - "dynamic": false, - "info": "Output Format. Use 'Text' to extract the text from the HTML or 'Raw HTML' for the raw HTML content.", - "name": "format", + "tool_mode": false, + "trace_as_metadata": true, "options": [ "Text", "Raw HTML" ], - "placeholder": "", + "combobox": false, "required": false, + "placeholder": "", "show": true, + "name": "format", + "value": "Text", + "display_name": "Output Format", + "advanced": false, + "dynamic": false, + "info": "Output Format. Use 'Text' to extract the text from the HTML or 'Raw HTML' for the raw HTML content.", "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, "type": "str", - "value": "Text" + "_input_type": "DropdownInput" }, "urls": { - "_input_type": "MessageTextInput", - "advanced": false, - "display_name": "URLs", - "dynamic": false, - "info": "Enter one or more URLs, by clicking the '+' button.", - "input_types": [ - "Message" - ], - "list": true, - "load_from_db": false, - "name": "urls", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, + "load_from_db": false, + "list": true, + "list_add_label": "Add URL", + "required": false, + "placeholder": "Enter a URL...", + "show": true, + "name": "urls", + "value": "", + "display_name": "URLs", + "advanced": false, + "input_types": [ + "Message" + ], + "dynamic": false, + "info": "", + "title_case": false, "type": "str", - "value": "" + "_input_type": "MessageTextInput" + }, + "tools_metadata": { + "tool_mode": false, + "is_list": true, + "list_add_label": "Add More", + "table_schema": { + "columns": [ + { + "name": "name", + "display_name": "Tool Name", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Specify the name of the tool.", + "disable_edit": false, + "edit_mode": "inline", + "formatter": "text" + }, + { + "name": "description", + "display_name": "Tool Description", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Describe the purpose of the tool.", + "disable_edit": false, + "edit_mode": "popover", + "formatter": "text" + }, + { + "name": "tags", + "display_name": "Tool Identifiers", + "sortable": false, + "filterable": false, + "type": "text", + "description": "The default identifiers for the tools and cannot be changed.", + "disable_edit": true, + "edit_mode": "inline", + "formatter": "text" + }, + { + "name": "commands", + "display_name": "Commands", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Add commands to the tool. These commands will be used to run the tool. Start all commands with a `/`. You can add multiple commands separated by a comma.\nExample: `/command1`, `/command2`, `/command3`", + "disable_edit": false, + "edit_mode": "inline", + "formatter": "text" + } + ] + }, + "trigger_text": "", + "trigger_icon": "Hammer", + "table_icon": "Hammer", + "table_options": { + "block_add": true, + "block_delete": true, + "block_edit": true, + "block_sort": true, + "block_filter": true, + "block_hide": true, + "block_select": true, + "hide_options": true, + "field_parsers": { + "name": [ + "snake_case", + "no_blank" + ], + "commands": "commands" + }, + "description": "Modify tool names and descriptions to help agents understand when to use each tool." + }, + "trace_as_metadata": true, + "required": false, + "placeholder": "", + "show": true, + "name": "tools_metadata", + "value": [ + { + "name": "URL-fetch_content", + "description": "fetch_content() - Load and retrive data from specified URLs.", + "tags": [ + "URL-fetch_content" + ] + }, + { + "name": "URL-fetch_content_text", + "description": "fetch_content_text() - Load and retrive data from specified URLs.", + "tags": [ + "URL-fetch_content_text" + ] + }, + { + "name": "URL-as_dataframe", + "description": "as_dataframe() - Load and retrive data from specified URLs.", + "tags": [ + "URL-as_dataframe" + ] + } + ], + "display_name": "Edit tools", + "advanced": false, + "dynamic": false, + "info": "", + "real_time_refresh": true, + "title_case": false, + "type": "table", + "_input_type": "TableInput" } }, - "tool_mode": false + "description": "Load and retrive data from specified URLs.", + "icon": "layout-template", + "base_classes": [ + "Data", + "DataFrame", + "Message" + ], + "display_name": "URL", + "documentation": "", + "minimized": false, + "custom_fields": {}, + "output_types": [], + "pinned": false, + "conditional_paths": [], + "frozen": false, + "outputs": [ + { + "types": [ + "Tool" + ], + "selected": "Tool", + "name": "component_as_tool", + "hidden": null, + "display_name": "Toolset", + "method": "to_toolkit", + "value": "__UNDEFINED__", + "cache": true, + "required_inputs": null + } + ], + "field_order": [ + "urls", + "format" + ], + "beta": false, + "legacy": false, + "edited": false, + "metadata": {}, + "lf_version": "1.1.1", + "tool_mode": true }, - "type": "URL" + "type": "URL", + "description": "Load and retrive data from specified URLs.", + "display_name": "URL" }, - "id": "URL-mRzJq", + "id": "URL-vRJK9", "measured": { - "height": 319, - "width": 320 + "height": 453, + "width": 360 }, "position": { - "x": 1288.1729287385363, - "y": 240 + "x": 1225.8773509111968, + "y": 27.333577318641687 }, - "selected": false, - "type": "genericNode" + "selected": true, + "type": "genericNode", + "dragging": false }, { "data": { - "id": "note-SOOQu", + "id": "note-AfssQ", "node": { "description": "# 📖 README\nRun an Agent with URL and Calculator tools available for its use. \nThe Agent decides which tool to use to solve a problem.\n## Quick start\n\n1. Add your OpenAI API key to the Agent.\n2. Open the Playground and chat with the Agent. Request some information about a recipe, and then ask to add two numbers together. In the responses, the Agent will use different tools to solve different problems.\n\n## Next steps\nConnect more tools to the Agent to create your perfect assistant.\n\nFor more, see the [Langflow docs](https://docs.langflow.org/agents-tool-calling-agent-component).", "display_name": "", @@ -1380,10 +1392,10 @@ }, "type": "note" }, - "id": "note-SOOQu", + "id": "note-AfssQ", "measured": { - "height": 325, - "width": 325 + "height": 328, + "width": 328 }, "position": { "x": 660, @@ -1394,7 +1406,7 @@ }, { "data": { - "id": "note-YaXmP", + "id": "note-TrpKI", "node": { "description": "### 💡 Add your OpenAI API key here👇", "display_name": "", @@ -1405,10 +1417,10 @@ }, "type": "note" }, - "id": "note-YaXmP", + "id": "note-TrpKI", "measured": { - "height": 324, - "width": 324 + "height": 326, + "width": 326 }, "position": { "x": 1648.6876745095624, @@ -1418,124 +1430,322 @@ "type": "noteNode" }, { + "id": "CalculatorComponent-lHyX4", + "type": "genericNode", + "position": { + "x": 1233.166256931297, + "y": 514.7544001650839 + }, "data": { - "id": "CalculatorTool-d6fIp", "node": { - "base_classes": [ - "Data", - "Tool" - ], - "beta": false, - "category": "tools", - "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", - "key": "CalculatorTool", - "legacy": false, - "metadata": {}, - "minimized": false, - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Data", - "method": "run_model", - "name": "api_run_model", - "required_inputs": [], - "selected": "Data", - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - }, - { - "cache": true, - "display_name": "Tool", - "method": "build_tool", - "name": "api_build_tool", - "required_inputs": [], - "selected": "Tool", - "types": [ - "Tool" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "score": 0.001, "template": { "_type": "Component", "code": { - "advanced": true, - "dynamic": true, + "type": "code", + "required": true, + "placeholder": "", + "list": false, + "show": true, + "multiline": true, + "value": "import ast\nimport operator\nfrom collections.abc import Callable\n\nfrom langflow.custom import Component\nfrom langflow.inputs import MessageTextInput\nfrom langflow.io import Output\nfrom langflow.schema import Data\n\n\nclass CalculatorComponent(Component):\n display_name = \"Calculator\"\n description = \"Perform basic arithmetic operations on a given expression.\"\n icon = \"calculator\"\n\n # Cache operators dictionary as a class variable\n OPERATORS: dict[type[ast.operator], Callable] = {\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 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 tool_mode=True,\n ),\n ]\n\n outputs = [\n Output(display_name=\"Data\", name=\"result\", type_=Data, method=\"evaluate_expression\"),\n ]\n\n def _eval_expr(self, node: ast.AST) -> float:\n \"\"\"Evaluate an AST node recursively.\"\"\"\n if isinstance(node, ast.Constant):\n if isinstance(node.value, int | float):\n return float(node.value)\n error_msg = f\"Unsupported constant type: {type(node.value).__name__}\"\n raise TypeError(error_msg)\n if isinstance(node, ast.Num): # For backwards compatibility\n if isinstance(node.n, int | float):\n return float(node.n)\n error_msg = f\"Unsupported number type: {type(node.n).__name__}\"\n raise TypeError(error_msg)\n\n if isinstance(node, ast.BinOp):\n op_type = type(node.op)\n if op_type not in self.OPERATORS:\n error_msg = f\"Unsupported binary operator: {op_type.__name__}\"\n raise TypeError(error_msg)\n\n left = self._eval_expr(node.left)\n right = self._eval_expr(node.right)\n return self.OPERATORS[op_type](left, right)\n\n error_msg = f\"Unsupported operation or expression type: {type(node).__name__}\"\n raise TypeError(error_msg)\n\n def evaluate_expression(self) -> Data:\n \"\"\"Evaluate the mathematical expression and return the result.\"\"\"\n try:\n tree = ast.parse(self.expression, mode=\"eval\")\n result = self._eval_expr(tree.body)\n\n formatted_result = f\"{float(result):.6f}\".rstrip(\"0\").rstrip(\".\")\n self.log(f\"Calculation result: {formatted_result}\")\n\n self.status = formatted_result\n return Data(data={\"result\": formatted_result})\n\n except ZeroDivisionError:\n error_message = \"Error: Division by zero\"\n self.status = error_message\n return Data(data={\"error\": error_message, \"input\": self.expression})\n\n except (SyntaxError, TypeError, KeyError, ValueError, AttributeError, OverflowError) as e:\n error_message = f\"Invalid expression: {e!s}\"\n self.status = error_message\n return Data(data={\"error\": error_message, \"input\": self.expression})\n\n def build(self):\n \"\"\"Return the main evaluation function.\"\"\"\n return self.evaluate_expression\n", "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 langchain_core.tools import ToolException\nfrom loguru import logger\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._eval_expr_with_error,\n args_schema=self.CalculatorToolSchema,\n )\n\n def _eval_expr(self, node):\n if isinstance(node, ast.Num):\n return node.n\n if isinstance(node, ast.BinOp):\n left_val = self._eval_expr(node.left)\n right_val = self._eval_expr(node.right)\n return self.operators[type(node.op)](left_val, right_val)\n if isinstance(node, ast.UnaryOp):\n operand_val = self._eval_expr(node.operand)\n return self.operators[type(node.op)](operand_val)\n if isinstance(node, ast.Call):\n msg = (\n \"Function calls like sqrt(), sin(), cos() etc. are not supported. \"\n \"Only basic arithmetic operations (+, -, *, /, **) are allowed.\"\n )\n raise TypeError(msg)\n msg = f\"Unsupported operation or expression type: {type(node).__name__}\"\n raise TypeError(msg)\n\n def _eval_expr_with_error(self, expression: str) -> list[Data]:\n try:\n return self._evaluate_expression(expression)\n except Exception as e:\n raise ToolException(str(e)) from e\n\n def _evaluate_expression(self, expression: str) -> list[Data]:\n try:\n # Parse the expression and evaluate it\n tree = ast.parse(expression, mode=\"eval\")\n result = self._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: {e}\"\n self.status = error_message\n return [Data(data={\"error\": error_message, \"input\": expression})]\n except ZeroDivisionError:\n error_message = \"Error: Division by zero\"\n self.status = error_message\n return [Data(data={\"error\": error_message, \"input\": expression})]\n except Exception as e: # noqa: BLE001\n logger.opt(exception=True).debug(\"Error evaluating expression\")\n error_message = f\"Error: {e}\"\n self.status = error_message\n return [Data(data={\"error\": error_message, \"input\": expression})]\n\n def __init__(self, *args, **kwargs):\n super().__init__(*args, **kwargs)\n self.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" + "name": "code", + "advanced": true, + "dynamic": true, + "info": "", + "load_from_db": false, + "title_case": false }, "expression": { - "_input_type": "MessageTextInput", - "advanced": false, + "tool_mode": true, + "trace_as_input": true, + "trace_as_metadata": true, + "load_from_db": false, + "list": false, + "list_add_label": "Add More", + "required": false, + "placeholder": "", + "show": true, + "name": "expression", + "value": "", "display_name": "Expression", - "dynamic": false, - "info": "The arithmetic expression to evaluate (e.g., '4*4*(33/22)+12-20').", + "advanced": false, "input_types": [ "Message" ], - "list": false, - "load_from_db": false, - "name": "expression", - "placeholder": "", - "required": false, - "show": true, + "dynamic": false, + "info": "The arithmetic expression to evaluate (e.g., '4*4*(33/22)+12-20').", "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, "type": "str", - "value": "" + "_input_type": "MessageTextInput" + }, + "tools_metadata": { + "tool_mode": false, + "is_list": true, + "list_add_label": "Add More", + "table_schema": { + "columns": [ + { + "name": "name", + "display_name": "Tool Name", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Specify the name of the tool.", + "disable_edit": false, + "edit_mode": "inline", + "formatter": "text" + }, + { + "name": "description", + "display_name": "Tool Description", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Describe the purpose of the tool.", + "disable_edit": false, + "edit_mode": "popover", + "formatter": "text" + }, + { + "name": "tags", + "display_name": "Tool Identifiers", + "sortable": false, + "filterable": false, + "type": "text", + "description": "The default identifiers for the tools and cannot be changed.", + "disable_edit": true, + "edit_mode": "inline", + "formatter": "text" + }, + { + "name": "commands", + "display_name": "Commands", + "sortable": false, + "filterable": false, + "type": "text", + "description": "Add commands to the tool. These commands will be used to run the tool. Start all commands with a `/`. You can add multiple commands separated by a comma.\nExample: `/command1`, `/command2`, `/command3`", + "disable_edit": false, + "edit_mode": "inline", + "formatter": "text" + } + ] + }, + "trigger_text": "", + "trigger_icon": "Hammer", + "table_icon": "Hammer", + "table_options": { + "block_add": true, + "block_delete": true, + "block_edit": true, + "block_sort": true, + "block_filter": true, + "block_hide": true, + "block_select": true, + "hide_options": true, + "field_parsers": { + "name": [ + "snake_case", + "no_blank" + ], + "commands": "commands" + }, + "description": "Modify tool names and descriptions to help agents understand when to use each tool." + }, + "trace_as_metadata": true, + "required": false, + "placeholder": "", + "show": true, + "name": "tools_metadata", + "value": [ + { + "name": "None-evaluate_expression", + "description": "evaluate_expression() - Perform basic arithmetic operations on a given expression.", + "tags": [ + "None-evaluate_expression" + ] + } + ], + "display_name": "Edit tools", + "advanced": false, + "dynamic": false, + "info": "", + "real_time_refresh": true, + "title_case": false, + "type": "table", + "_input_type": "TableInput" } }, - "tool_mode": false + "description": "Perform basic arithmetic operations on a given expression.", + "icon": "calculator", + "base_classes": [ + "Data" + ], + "display_name": "Calculator", + "documentation": "", + "minimized": false, + "custom_fields": {}, + "output_types": [], + "pinned": false, + "conditional_paths": [], + "frozen": false, + "outputs": [ + { + "types": [ + "Tool" + ], + "selected": "Tool", + "name": "component_as_tool", + "hidden": null, + "display_name": "Toolset", + "method": "to_toolkit", + "value": "__UNDEFINED__", + "cache": true, + "required_inputs": null + } + ], + "field_order": [ + "expression" + ], + "beta": false, + "legacy": false, + "edited": false, + "metadata": {}, + "category": "tools", + "key": "CalculatorComponent", + "score": 0.001, + "lf_version": "1.1.1" }, "showNode": true, - "type": "CalculatorTool" - }, - "id": "CalculatorTool-d6fIp", - "measured": { - "height": 301, - "width": 320 - }, - "position": { - "x": 1263.0695485066078, - "y": 604.8992509251098 + "type": "CalculatorComponent", + "id": "CalculatorComponent-lHyX4" }, "selected": false, - "type": "genericNode" + "measured": { + "width": 360, + "height": 374 + }, + "dragging": false + } + ], + "edges": [ + { + "data": { + "sourceHandle": { + "dataType": "ChatInput", + "id": "ChatInput-8EBqM", + "name": "message", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "Agent-rl4Nb", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-ChatInput-8EBqM{œdataTypeœ:œChatInputœ,œidœ:œChatInput-8EBqMœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Agent-rl4Nb{œfieldNameœ:œinput_valueœ,œidœ:œAgent-rl4Nbœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "ChatInput-8EBqM", + "sourceHandle": "{œdataTypeœ:œChatInputœ,œidœ:œChatInput-8EBqMœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}", + "target": "Agent-rl4Nb", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œAgent-rl4Nbœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "className": "", + "animated": false + }, + { + "data": { + "sourceHandle": { + "dataType": "Agent", + "id": "Agent-rl4Nb", + "name": "response", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-f5pzU", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-Agent-rl4Nb{œdataTypeœ:œAgentœ,œidœ:œAgent-rl4Nbœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-f5pzU{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-f5pzUœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "Agent-rl4Nb", + "sourceHandle": "{œdataTypeœ:œAgentœ,œidœ:œAgent-rl4Nbœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}", + "target": "ChatOutput-f5pzU", + "targetHandle": "{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-f5pzUœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "className": "", + "animated": false + }, + { + "source": "CalculatorComponent-lHyX4", + "sourceHandle": "{œdataTypeœ:œCalculatorComponentœ,œidœ:œCalculatorComponent-lHyX4œ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}", + "target": "Agent-rl4Nb", + "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgent-rl4Nbœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", + "data": { + "targetHandle": { + "fieldName": "tools", + "id": "Agent-rl4Nb", + "inputTypes": [ + "Tool" + ], + "type": "other" + }, + "sourceHandle": { + "dataType": "CalculatorComponent", + "id": "CalculatorComponent-lHyX4", + "name": "component_as_tool", + "output_types": [ + "Tool" + ] + } + }, + "id": "xy-edge__CalculatorComponent-lHyX4{œdataTypeœ:œCalculatorComponentœ,œidœ:œCalculatorComponent-lHyX4œ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}-Agent-rl4Nb{œfieldNameœ:œtoolsœ,œidœ:œAgent-rl4Nbœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", + "animated": false, + "className": "" + }, + { + "source": "URL-vRJK9", + "sourceHandle": "{œdataTypeœ:œURLœ,œidœ:œURL-vRJK9œ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}", + "target": "Agent-rl4Nb", + "targetHandle": "{œfieldNameœ:œtoolsœ,œidœ:œAgent-rl4Nbœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", + "data": { + "targetHandle": { + "fieldName": "tools", + "id": "Agent-rl4Nb", + "inputTypes": [ + "Tool" + ], + "type": "other" + }, + "sourceHandle": { + "dataType": "URL", + "id": "URL-vRJK9", + "name": "component_as_tool", + "output_types": [ + "Tool" + ] + } + }, + "id": "xy-edge__URL-vRJK9{œdataTypeœ:œURLœ,œidœ:œURL-vRJK9œ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}-Agent-rl4Nb{œfieldNameœ:œtoolsœ,œidœ:œAgent-rl4Nbœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", + "animated": false, + "className": "" } ], "viewport": { - "x": -41, - "y": 2, - "zoom": 1 + "x": -262.4937282538692, + "y": 26.682431129452084, + "zoom": 0.698419234362548 } }, "description": "A simple but powerful starter agent.",