From 017a0a463bc1492c9f2740b0431aa9fa797e670d Mon Sep 17 00:00:00 2001 From: Edwin Jose Date: Mon, 31 Mar 2025 12:57:30 -0400 Subject: [PATCH] feat: deprecate Parsing component and replace them in starter projects (#6697) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: fixed the parser component * fix: fixed parser component test * fix: ruff error * chore: rename input * chore: remove beta attribute * update * updated template with legacy as true * updated templates * [autofix.ci] apply automated fixes * ✨ (freeze.spec.ts): add new test steps to check sidebar options and legacy switch functionality ✨ (similarity.spec.ts): add new test steps to check sidebar options and legacy switch functionality ✨ (loop-component.spec.ts): add new test steps to check sidebar options and legacy switch functionality, as well as zoom out and expand button modal functionality * remove-copy-numbers-from-template-titles * update-blog-writer-template-readme * update-document-qa-template-notes * update-market-research-template-notes * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes * ✨ (filterEdge-shard-0.spec.ts, freeze.spec.ts, Portfolio Website Code Generator.spec.ts, decisionFlow.spec.ts, similarity.spec.ts, generalBugs-shard-9.spec.ts, codeAreaModalComponent.spec.ts, fileUploadComponent.spec.ts, nestedComponent.spec.ts, filterEdge-shard-1.spec.ts, loop-component.spec.ts, generalBugs-shard-12.spec.ts, add-legacy-components.ts): add function to handle legacy components in tests for improved test readability and maintainability * remove duplicated graph rag template * update changes * update Templates with new parser component * [autofix.ci] apply automated fixes * fix: remove name attribute * fix: autofix.ci patch * ✨ (stop-building.spec.ts): add new function addLegacyComponents to include legacy components in the test scenario 🔧 (decisionFlow.spec.ts): increase timeout from 500ms to 2000ms for better stability and reliability in waiting for selectors to appear --------- Co-authored-by: italojohnny Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: cristhianzl Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com> --- .../components/processing/parse_data.py | 1 + .../components/processing/parse_dataframe.py | 1 + .../starter_projects/Blog Writer.json | 599 ++++---- .../starter_projects/Document Q&A.json | 736 ++++++---- .../Financial Report Parser.json | 273 ++-- .../Image Sentiment Analysis.json | 1258 ++++++++++------- .../starter_projects/LoopTemplate.json | 588 ++++---- .../starter_projects/Market Research.json | 766 +++++----- .../starter_projects/Meeting Summary.json | 685 ++++----- .../Portfolio Website Code Generator.json | 1038 +++++++------- .../Text Sentiment Analysis.json | 474 ++----- .../starter_projects/Vector Store RAG.json | 656 +++++---- .../starter_projects/Youtube Analysis.json | 626 ++++---- .../core/features/filterEdge-shard-0.spec.ts | 9 +- .../tests/core/features/freeze.spec.ts | 4 +- .../tests/core/features/stop-building.spec.ts | 3 + .../Portfolio Website Code Generator.spec.ts | 4 +- .../core/integrations/decisionFlow.spec.ts | 39 +- .../core/integrations/similarity.spec.ts | 4 + .../regression/generalBugs-shard-9.spec.ts | 7 +- .../core/unit/codeAreaModalComponent.spec.ts | 7 +- .../core/unit/fileUploadComponent.spec.ts | 3 + .../tests/core/unit/nestedComponent.spec.ts | 9 +- .../features/filterEdge-shard-1.spec.ts | 10 +- .../extended/features/loop-component.spec.ts | 15 +- .../regression/generalBugs-shard-12.spec.ts | 9 +- .../tests/utils/add-legacy-components.ts | 9 + 27 files changed, 4022 insertions(+), 3811 deletions(-) create mode 100644 src/frontend/tests/utils/add-legacy-components.ts diff --git a/src/backend/base/langflow/components/processing/parse_data.py b/src/backend/base/langflow/components/processing/parse_data.py index f6d865e77..ff376bdd1 100644 --- a/src/backend/base/langflow/components/processing/parse_data.py +++ b/src/backend/base/langflow/components/processing/parse_data.py @@ -10,6 +10,7 @@ class ParseDataComponent(Component): description = "Convert Data objects into Messages using any {field_name} from input data." icon = "message-square" name = "ParseData" + legacy = True metadata = { "legacy_name": "Parse Data", } diff --git a/src/backend/base/langflow/components/processing/parse_dataframe.py b/src/backend/base/langflow/components/processing/parse_dataframe.py index f4084591e..ec6cfdf12 100644 --- a/src/backend/base/langflow/components/processing/parse_dataframe.py +++ b/src/backend/base/langflow/components/processing/parse_dataframe.py @@ -11,6 +11,7 @@ class ParseDataFrameComponent(Component): ) icon = "braces" name = "ParseDataFrame" + legacy = True inputs = [ DataFrameInput(name="df", display_name="DataFrame", info="The DataFrame to convert to text rows."), diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json b/src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json index fb169f66d..bce00e87e 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json @@ -1,41 +1,13 @@ { "data": { "edges": [ - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-4Sckw", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "references", - "id": "Prompt-65R68", - "inputTypes": [ - "Message", - "Text" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-4Sckw{œdataTypeœ:œParseDataœ,œidœ:œParseData-4Sckwœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-Prompt-65R68{œfieldNameœ:œreferencesœ,œidœ:œPrompt-65R68œ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", - "source": "ParseData-4Sckw", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-4Sckwœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-65R68", - "targetHandle": "{œfieldNameœ: œreferencesœ, œidœ: œPrompt-65R68œ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" - }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "TextInput", - "id": "TextInput-t88FI", + "id": "TextInput-3OSew", "name": "text", "output_types": [ "Message" @@ -43,7 +15,7 @@ }, "targetHandle": { "fieldName": "instructions", - "id": "Prompt-65R68", + "id": "Prompt-1l6Me", "inputTypes": [ "Message", "Text" @@ -51,18 +23,20 @@ "type": "str" } }, - "id": "reactflow__edge-TextInput-t88FI{œdataTypeœ:œTextInputœ,œidœ:œTextInput-t88FIœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-Prompt-65R68{œfieldNameœ:œinstructionsœ,œidœ:œPrompt-65R68œ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", - "source": "TextInput-t88FI", - "sourceHandle": "{œdataTypeœ: œTextInputœ, œidœ: œTextInput-t88FIœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-65R68", - "targetHandle": "{œfieldNameœ: œinstructionsœ, œidœ: œPrompt-65R68œ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" + "id": "reactflow__edge-TextInput-3OSew{œdataTypeœ:œTextInputœ,œidœ:œTextInput-3OSewœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-Prompt-1l6Me{œfieldNameœ:œinstructionsœ,œidœ:œPrompt-1l6Meœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "selected": false, + "source": "TextInput-3OSew", + "sourceHandle": "{œdataTypeœ: œTextInputœ, œidœ: œTextInput-3OSewœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-1l6Me", + "targetHandle": "{œfieldNameœ: œinstructionsœ, œidœ: œPrompt-1l6Meœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" }, { + "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "Prompt", - "id": "Prompt-65R68", + "id": "Prompt-1l6Me", "name": "prompt", "output_types": [ "Message" @@ -70,25 +44,27 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "OpenAIModel-MyAsQ", + "id": "OpenAIModel-TOE5z", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-Prompt-65R68{œdataTypeœ:œPromptœ,œidœ:œPrompt-65R68œ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-MyAsQ{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-MyAsQœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "source": "Prompt-65R68", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-65R68œ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-MyAsQ", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-MyAsQœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "id": "reactflow__edge-Prompt-1l6Me{œdataTypeœ:œPromptœ,œidœ:œPrompt-1l6Meœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-TOE5z{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-TOE5zœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "Prompt-1l6Me", + "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-1l6Meœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-TOE5z", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-TOE5zœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { + "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-MyAsQ", + "id": "OpenAIModel-TOE5z", "name": "text_output", "output_types": [ "Message" @@ -96,7 +72,7 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-BE4YI", + "id": "ChatOutput-8AUxp", "inputTypes": [ "Data", "DataFrame", @@ -105,202 +81,78 @@ "type": "str" } }, - "id": "reactflow__edge-OpenAIModel-MyAsQ{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-MyAsQœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-BE4YI{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-BE4YIœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "source": "OpenAIModel-MyAsQ", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-MyAsQœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-BE4YI", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-BE4YIœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" + "id": "reactflow__edge-OpenAIModel-TOE5z{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-TOE5zœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-8AUxp{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-8AUxpœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "OpenAIModel-TOE5z", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-TOE5zœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-8AUxp", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-8AUxpœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" }, { + "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "URL", - "id": "URL-EPEnt", - "name": "data", + "id": "URL-MjSj8", + "name": "dataframe", "output_types": [ - "Data" + "DataFrame" ] }, "targetHandle": { - "fieldName": "data", - "id": "ParseData-4Sckw", + "fieldName": "input_data", + "id": "parser-Sbhw7", "inputTypes": [ + "DataFrame", "Data" ], "type": "other" } }, - "id": "reactflow__edge-URL-EPEnt{œdataTypeœ:œURLœ,œidœ:œURL-EPEntœ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-ParseData-4Sckw{œfieldNameœ:œdataœ,œidœ:œParseData-4Sckwœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", - "source": "URL-EPEnt", - "sourceHandle": "{œdataTypeœ: œURLœ, œidœ: œURL-EPEntœ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-4Sckw", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-4Sckwœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" + "id": "xy-edge__URL-MjSj8{œdataTypeœ:œURLœ,œidœ:œURL-MjSj8œ,œnameœ:œdataframeœ,œoutput_typesœ:[œDataFrameœ]}-parser-Sbhw7{œfieldNameœ:œinput_dataœ,œidœ:œparser-Sbhw7œ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", + "selected": false, + "source": "URL-MjSj8", + "sourceHandle": "{œdataTypeœ: œURLœ, œidœ: œURL-MjSj8œ, œnameœ: œdataframeœ, œoutput_typesœ: [œDataFrameœ]}", + "target": "parser-Sbhw7", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-Sbhw7œ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-Sbhw7", + "name": "parsed_text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "references", + "id": "Prompt-1l6Me", + "inputTypes": [ + "Message", + "Text" + ], + "type": "str" + } + }, + "id": "xy-edge__parser-Sbhw7{œdataTypeœ:œparserœ,œidœ:œparser-Sbhw7œ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-Prompt-1l6Me{œfieldNameœ:œreferencesœ,œidœ:œPrompt-1l6Meœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "selected": false, + "source": "parser-Sbhw7", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-Sbhw7œ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-1l6Me", + "targetHandle": "{œfieldNameœ: œreferencesœ, œidœ: œPrompt-1l6Meœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" } ], "nodes": [ - { - "data": { - "description": "Convert Data into plain text following a specified template.", - "display_name": "Parse Data", - "id": "ParseData-4Sckw", - "node": { - "base_classes": [ - "Message" - ], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert Data into plain text following a specified template.", - "display_name": "Parse Data", - "documentation": "", - "edited": false, - "field_order": [ - "data", - "template", - "sep" - ], - "frozen": false, - "icon": "message-square", - "legacy": false, - "lf_version": "1.0.19.post2", - "metadata": { - "legacy_name": "Parse Data" - }, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Message", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - }, - { - "allows_loop": false, - "cache": true, - "display_name": "Data List", - "method": "parse_data_as_list", - "name": "data_list", - "selected": "Data", - "tool_mode": true, - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" - }, - "data": { - "advanced": false, - "display_name": "Data", - "dynamic": false, - "info": "The data to convert to text.", - "input_types": [ - "Data" - ], - "list": true, - "name": "data", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "", - "list": false, - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template to use for formatting the data. It can contain the keys {text}, {data} or any other key in the Data.", - "input_types": [ - "Message" - ], - "list": false, - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "{text}" - } - } - }, - "type": "ParseData" - }, - "dragging": false, - "height": 302, - "id": "ParseData-4Sckw", - "measured": { - "height": 302, - "width": 320 - }, - "position": { - "x": 955.6736985046297, - "y": 702.7003891105396 - }, - "positionAbsolute": { - "x": 955.6736985046297, - "y": 702.7003891105396 - }, - "selected": false, - "type": "genericNode", - "width": 320 - }, { "data": { "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", - "id": "Prompt-65R68", + "id": "Prompt-1l6Me", "node": { "base_classes": [ "Message" @@ -323,7 +175,7 @@ "frozen": false, "icon": "prompts", "legacy": false, - "lf_version": "1.0.19.post2", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -454,7 +306,7 @@ }, "dragging": false, "height": 433, - "id": "Prompt-65R68", + "id": "Prompt-1l6Me", "measured": { "height": 433, "width": 320 @@ -475,7 +327,7 @@ "data": { "description": "Get text inputs from the Playground.", "display_name": "Instructions", - "id": "TextInput-t88FI", + "id": "TextInput-3OSew", "node": { "base_classes": [ "Message" @@ -493,7 +345,7 @@ "frozen": false, "icon": "type", "legacy": false, - "lf_version": "1.0.19.post2", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -560,7 +412,7 @@ }, "dragging": false, "height": 234, - "id": "TextInput-t88FI", + "id": "TextInput-3OSew", "measured": { "height": 234, "width": 320 @@ -581,7 +433,7 @@ "data": { "description": "Display a chat message in the Playground.", "display_name": "Chat Output", - "id": "ChatOutput-BE4YI", + "id": "ChatOutput-8AUxp", "node": { "base_classes": [ "Message" @@ -604,7 +456,7 @@ "frozen": false, "icon": "MessagesSquare", "legacy": false, - "lf_version": "1.0.19.post2", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -846,7 +698,7 @@ }, "dragging": false, "height": 234, - "id": "ChatOutput-BE4YI", + "id": "ChatOutput-8AUxp", "measured": { "height": 234, "width": 320 @@ -859,52 +711,15 @@ "x": 2113.228183852361, "y": 594.6116538574528 }, - "selected": false, + "selected": true, "type": "genericNode", "width": 320 }, { "data": { - "id": "note-lriuW", + "id": "note-NjIzK", "node": { - "description": "## URL Component Setup\n\n**Purpose:**\nFetch and process content from the web to use as reference material for creating a blog post.\n\n**Instructions:**\n1. **Input URLs**: List the URLs of web pages whose content you want to fetch. Ensure the URLs start with `http://` or `https://`.\n2. **Select Output Format**:\n - **Text**: To extract plain text from the pages.\n - **Raw HTML**: To retrieve the raw HTML content for advanced uses.\n\n**Tips**:\n- Double-check URL formats to prevent any data fetching errors.\n- Use the '+' button to add multiple URLs as needed for comprehensive references.\n", - "display_name": "", - "documentation": "", - "template": { - "backgroundColor": "blue" - } - }, - "type": "note" - }, - "dragging": false, - "height": 324, - "id": "note-lriuW", - "measured": { - "height": 324, - "width": 325 - }, - "position": { - "x": 484.73635938598477, - "y": 153.29803159918163 - }, - "positionAbsolute": { - "x": 484.73635938598477, - "y": 153.29803159918163 - }, - "resizing": false, - "selected": false, - "style": { - "height": 329, - "width": 324 - }, - "type": "noteNode", - "width": 324 - }, - { - "data": { - "id": "note-1oPzi", - "node": { - "description": "# Blog Writing Flow Overview\n\n**Workflow Description:**\nThis flow assists in creating a blog post by using content fetched from URLs and user-provided instructions. It combines external references and user inputs to generate coherent and context-rich text.\n\n**Components**:\n1. **URL Component**: Fetches reference content from specified web pages.\n2. **Parse Data**: Converts the fetched content into a text format.\n3. **Text Input**: Accepts user-specific instructions for the blog post.\n4. **Prompt with Variables**: Merges references and instructions into a dynamic writing prompt.\n5. **OpenAI Model**: Generates the blog post using an AI language model.\n6. **Chat Output**: Displays the final blog text for user review and further refinement.\n\n**Steps to Execute**:\n1. Enter the relevant URLs and specify the output format in the **URL Component**.\n2. Provide detailed writing **Instructions** for AI to follow.\n3. Run the flow to generate the blog and view the result in **Chat Output**.\n\n**Benefits**:\n- Simplifies blog creation by using AI to structure and write content.\n- Incorporates comprehensive reference material to enhance post depth and accuracy.", + "description": "# Blog Writing Flow Overview\n\nCreate a blog post by using content fetched from URLs and user-provided instructions.\n\n## Prerequisites\n\n* An [OpenAI API key](https://platform.openai.com/)\n\n## Quickstart\n\n1. Paste your OpenAI API key in the **OpenAI** model component.\n2. In the **URL** component, enter URLs you want to fetch content from. Ensure they start with `http://` or `https://`.\n3. Open the **Playground**. A blog post is written from the content fetched by the **URL** component.", "display_name": "", "documentation": "", "template": {} @@ -912,15 +727,15 @@ "type": "note" }, "dragging": false, - "height": 486, - "id": "note-1oPzi", + "height": 582, + "id": "note-NjIzK", "measured": { - "height": 486, - "width": 325 + "height": 582, + "width": 508 }, "position": { - "x": -78.41970365609802, - "y": 405.04114164010207 + "x": -86.00395676688996, + "y": 408.833268195498 }, "positionAbsolute": { "x": -78.41970365609802, @@ -933,48 +748,11 @@ "width": 562 }, "type": "noteNode", - "width": 324 + "width": 507 }, { "data": { - "id": "note-qhsOB", - "node": { - "description": "## Get Your OpenAI API Key\n**Steps**:\n1. **Visit** [OpenAI's API Key Page](https://platform.openai.com/api-keys).\n\n2. **Log In/Sign Up**:\n - Log in or create a new OpenAI account.\n\n3. **Generate API Key**:\n - Click \"Create New Secret Key\" to obtain your key.\n\n4. **Store Your Key Securely**:\n - Note it down as it will only display once.\n\n5. **Enter API Key**:\n - Input your key in the OpenAI API Key field within the component setup.\n\nKeep your key safe and manage it responsibly!", - "display_name": "", - "documentation": "", - "template": { - "backgroundColor": "rose" - } - }, - "type": "note" - }, - "dragging": false, - "height": 324, - "id": "note-qhsOB", - "measured": { - "height": 324, - "width": 325 - }, - "position": { - "x": 1702.078126574358, - "y": 121.36154223045867 - }, - "positionAbsolute": { - "x": 1703.974189852056, - "y": 125.15366878585462 - }, - "resizing": false, - "selected": false, - "style": { - "height": 324, - "width": 343 - }, - "type": "noteNode", - "width": 324 - }, - { - "data": { - "id": "OpenAIModel-MyAsQ", + "id": "OpenAIModel-TOE5z", "node": { "base_classes": [ "LanguageModel", @@ -1005,6 +783,7 @@ "icon": "OpenAI", "key": "OpenAIModel", "legacy": false, + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -1061,7 +840,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -1342,9 +1121,9 @@ "type": "OpenAIModel" }, "dragging": false, - "id": "OpenAIModel-MyAsQ", + "id": "OpenAIModel-TOE5z", "measured": { - "height": 653, + "height": 525, "width": 320 }, "position": { @@ -1356,7 +1135,7 @@ }, { "data": { - "id": "URL-EPEnt", + "id": "URL-MjSj8", "node": { "base_classes": [ "Data", @@ -1379,6 +1158,7 @@ "icon": "layout-template", "key": "URL", "legacy": false, + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -1539,9 +1319,9 @@ "type": "URL" }, "dragging": false, - "id": "URL-EPEnt", + "id": "URL-MjSj8", "measured": { - "height": 465, + "height": 591, "width": 320 }, "position": { @@ -1550,21 +1330,194 @@ }, "selected": false, "type": "genericNode" + }, + { + "data": { + "id": "parser-Sbhw7", + "node": { + "base_classes": [ + "Message" + ], + "beta": false, + "category": "processing", + "conditional_paths": [], + "custom_fields": {}, + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", + "documentation": "", + "edited": false, + "field_order": [ + "mode", + "pattern", + "input_data", + "sep" + ], + "frozen": false, + "icon": "braces", + "key": "parser", + "legacy": false, + "lf_version": "1.2.0", + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", + "selected": "Message", + "tool_mode": true, + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 2.220446049250313e-16, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n name = \"parser\"\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" + }, + "input_data": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Data or DataFrame", + "dynamic": false, + "info": "Accepts either a DataFrame or a Data object.", + "input_types": [ + "DataFrame", + "Data" + ], + "list": false, + "list_add_label": "Add More", + "name": "input_data", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Parser" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "Text: {text}" + }, + "sep": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Separator", + "dynamic": false, + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "sep", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "\n" + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "parser" + }, + "dragging": false, + "id": "parser-Sbhw7", + "measured": { + "height": 395, + "width": 320 + }, + "position": { + "x": 943.2290441659609, + "y": 730.1044355558303 + }, + "selected": false, + "type": "genericNode" } ], "viewport": { - "x": 107.17740467666556, - "y": 281.84175643433355, - "zoom": 0.5274085584390961 + "x": 111.03999034137428, + "y": 102.10320934268941, + "zoom": 0.525810790842613 } }, "description": "Auto-generate a customized blog post from instructions and referenced articles.", "endpoint_name": null, - "gradient": "4", - "icon": "NotebookPen", - "id": "8b12aa0f-8b59-4806-a01f-5e545b5b1688", + "id": "6b792874-e7e4-4ef5-bb3f-ac22a44342a4", "is_component": false, - "last_tested_version": "1.0.19.post2", + "last_tested_version": "1.2.0", "name": "Blog Writer", "tags": [ "chatbots", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json b/src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json index ff4197f67..a81ef81e5 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json @@ -2,119 +2,146 @@ "data": { "edges": [ { - "className": "", - "data": { - "sourceHandle": { - "dataType": "File", - "id": "File-GwJQZ", - "name": "data", - "output_types": ["Data"] - }, - "targetHandle": { - "fieldName": "data", - "id": "ParseData-BbvKb", - "inputTypes": ["Data"], - "type": "other" - } - }, - "id": "reactflow__edge-File-GwJQZ{œdataTypeœ:œFileœ,œidœ:œFile-GwJQZœ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-ParseData-BbvKb{œfieldNameœ:œdataœ,œidœ:œParseData-BbvKbœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", - "selected": false, - "source": "File-GwJQZ", - "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-GwJQZœ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-BbvKb", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-BbvKbœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" - }, - { - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-BbvKb", - "name": "text", - "output_types": ["Message"] - }, - "targetHandle": { - "fieldName": "Document", - "id": "Prompt-yvZHT", - "inputTypes": ["Message", "Text"], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-BbvKb{œdataTypeœ:œParseDataœ,œidœ:œParseData-BbvKbœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-Prompt-yvZHT{œfieldNameœ:œDocumentœ,œidœ:œPrompt-yvZHTœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-BbvKb", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-BbvKbœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-yvZHT", - "targetHandle": "{œfieldNameœ: œDocumentœ, œidœ: œPrompt-yvZHTœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" - }, - { + "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "ChatInput", - "id": "ChatInput-li477", + "id": "ChatInput-82ow1", "name": "message", - "output_types": ["Message"] + "output_types": [ + "Message" + ] }, "targetHandle": { "fieldName": "input_value", - "id": "OpenAIModel-atkmo", - "inputTypes": ["Message"], + "id": "OpenAIModel-Xctjl", + "inputTypes": [ + "Message" + ], "type": "str" } }, - "id": "reactflow__edge-ChatInput-li477{œdataTypeœ:œChatInputœ,œidœ:œChatInput-li477œ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-atkmo{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-atkmoœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-82ow1{œdataTypeœ:œChatInputœ,œidœ:œChatInput-82ow1œ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-Xctjl{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-Xctjlœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "ChatInput-li477", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-li477œ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-atkmo", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-atkmoœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "ChatInput-82ow1", + "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-82ow1œ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-Xctjl", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-Xctjlœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { + "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "Prompt", - "id": "Prompt-yvZHT", + "id": "Prompt-yAr8f", "name": "prompt", - "output_types": ["Message"] + "output_types": [ + "Message" + ] }, "targetHandle": { "fieldName": "system_message", - "id": "OpenAIModel-atkmo", - "inputTypes": ["Message"], + "id": "OpenAIModel-Xctjl", + "inputTypes": [ + "Message" + ], "type": "str" } }, - "id": "reactflow__edge-Prompt-yvZHT{œdataTypeœ:œPromptœ,œidœ:œPrompt-yvZHTœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-atkmo{œfieldNameœ:œsystem_messageœ,œidœ:œOpenAIModel-atkmoœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-yAr8f{œdataTypeœ:œPromptœ,œidœ:œPrompt-yAr8fœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-Xctjl{œfieldNameœ:œsystem_messageœ,œidœ:œOpenAIModel-Xctjlœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Prompt-yvZHT", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-yvZHTœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-atkmo", - "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œOpenAIModel-atkmoœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "Prompt-yAr8f", + "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-yAr8fœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-Xctjl", + "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œOpenAIModel-Xctjlœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { + "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-atkmo", + "id": "OpenAIModel-Xctjl", "name": "text_output", - "output_types": ["Message"] + "output_types": [ + "Message" + ] }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-8pgwS", - "inputTypes": ["Data", "DataFrame", "Message"], + "id": "ChatOutput-hSEAB", + "inputTypes": [ + "Data", + "DataFrame", + "Message" + ], "type": "str" } }, - "id": "reactflow__edge-OpenAIModel-atkmo{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-atkmoœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-8pgwS{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-8pgwSœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-OpenAIModel-Xctjl{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-Xctjlœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-hSEAB{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-hSEABœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "OpenAIModel-atkmo", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-atkmoœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-8pgwS", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-8pgwSœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" + "source": "OpenAIModel-Xctjl", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-Xctjlœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-hSEAB", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-hSEABœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" + }, + { + "animated": false, + "data": { + "sourceHandle": { + "dataType": "File", + "id": "File-3BeiJ", + "name": "dataframe", + "output_types": [ + "DataFrame" + ] + }, + "targetHandle": { + "fieldName": "input_data", + "id": "parser-mO32W", + "inputTypes": [ + "DataFrame", + "Data" + ], + "type": "other" + } + }, + "id": "xy-edge__File-3BeiJ{œdataTypeœ:œFileœ,œidœ:œFile-3BeiJœ,œnameœ:œdataframeœ,œoutput_typesœ:[œDataFrameœ]}-parser-mO32W{œfieldNameœ:œinput_dataœ,œidœ:œparser-mO32Wœ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", + "selected": false, + "source": "File-3BeiJ", + "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-3BeiJœ, œnameœ: œdataframeœ, œoutput_typesœ: [œDataFrameœ]}", + "target": "parser-mO32W", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-mO32Wœ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-mO32W", + "name": "parsed_text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "Document", + "id": "Prompt-yAr8f", + "inputTypes": [ + "Message", + "Text" + ], + "type": "str" + } + }, + "id": "xy-edge__parser-mO32W{œdataTypeœ:œparserœ,œidœ:œparser-mO32Wœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-Prompt-yAr8f{œfieldNameœ:œDocumentœ,œidœ:œPrompt-yAr8fœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "selected": false, + "source": "parser-mO32W", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-mO32Wœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-yAr8f", + "targetHandle": "{œfieldNameœ: œDocumentœ, œidœ: œPrompt-yAr8fœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" } ], "nodes": [ @@ -122,9 +149,11 @@ "data": { "description": "Get chat inputs from the Playground.", "display_name": "Chat Input", - "id": "ChatInput-li477", + "id": "ChatInput-82ow1", "node": { - "base_classes": ["Message"], + "base_classes": [ + "Message" + ], "beta": false, "conditional_paths": [], "custom_fields": {}, @@ -155,7 +184,9 @@ "name": "message", "selected": "Message", "tool_mode": true, - "types": ["Message"], + "types": [ + "Message" + ], "value": "__UNDEFINED__" } ], @@ -168,7 +199,9 @@ "display_name": "Background Color", "dynamic": false, "info": "The background color of the icon.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "background_color", @@ -187,7 +220,9 @@ "display_name": "Icon", "dynamic": false, "info": "The icon of the message.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "chat_icon", @@ -285,7 +320,10 @@ "dynamic": false, "info": "Type of sender.", "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "placeholder": "", "required": false, "show": true, @@ -299,7 +337,9 @@ "display_name": "Sender Name", "dynamic": false, "info": "Name of the sender.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "sender_name", @@ -317,7 +357,9 @@ "display_name": "Session ID", "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "session_id", @@ -352,7 +394,9 @@ "display_name": "Text Color", "dynamic": false, "info": "The text color of the name", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "text_color", @@ -371,7 +415,7 @@ }, "dragging": false, "height": 234, - "id": "ChatInput-li477", + "id": "ChatInput-82ow1", "measured": { "height": 234, "width": 320 @@ -392,9 +436,11 @@ "data": { "description": "Display a chat message in the Playground.", "display_name": "Chat Output", - "id": "ChatOutput-8pgwS", + "id": "ChatOutput-hSEAB", "node": { - "base_classes": ["Message"], + "base_classes": [ + "Message" + ], "beta": false, "conditional_paths": [], "custom_fields": {}, @@ -428,7 +474,9 @@ "name": "message", "selected": "Message", "tool_mode": true, - "types": ["Message"], + "types": [ + "Message" + ], "value": "__UNDEFINED__" } ], @@ -441,7 +489,9 @@ "display_name": "Background Color", "dynamic": false, "info": "The background color of the icon.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "background_color", @@ -461,7 +511,9 @@ "display_name": "Icon", "dynamic": false, "info": "The icon of the message.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "chat_icon", @@ -517,7 +569,9 @@ "display_name": "Data Template", "dynamic": false, "info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "data_template", @@ -537,7 +591,11 @@ "display_name": "Text", "dynamic": false, "info": "Message to be passed as output.", - "input_types": ["Data", "DataFrame", "Message"], + "input_types": [ + "Data", + "DataFrame", + "Message" + ], "list": false, "load_from_db": false, "name": "input_value", @@ -558,7 +616,10 @@ "dynamic": false, "info": "Type of sender.", "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "placeholder": "", "required": false, "show": true, @@ -574,7 +635,9 @@ "display_name": "Sender Name", "dynamic": false, "info": "Name of the sender.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "sender_name", @@ -594,7 +657,9 @@ "display_name": "Session ID", "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "session_id", @@ -630,7 +695,9 @@ "display_name": "Text Color", "dynamic": false, "info": "The text color of the name", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "text_color", @@ -651,7 +718,7 @@ }, "dragging": false, "height": 234, - "id": "ChatOutput-8pgwS", + "id": "ChatOutput-hSEAB", "measured": { "height": 234, "width": 320 @@ -670,184 +737,9 @@ }, { "data": { - "description": "Convert Data into plain text following a specified template.", - "display_name": "Parse Data", - "id": "ParseData-BbvKb", + "id": "note-7pTJx", "node": { - "base_classes": ["Message"], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert Data into plain text following a specified template.", - "display_name": "Parse Data", - "documentation": "", - "edited": false, - "field_order": ["data", "template", "sep"], - "frozen": false, - "icon": "message-square", - "legacy": false, - "lf_version": "1.0.19.post2", - "metadata": { - "legacy_name": "Parse Data" - }, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Message", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": ["Message"], - "value": "__UNDEFINED__" - }, - { - "allows_loop": false, - "cache": true, - "display_name": "Data List", - "method": "parse_data_as_list", - "name": "data_list", - "selected": "Data", - "tool_mode": true, - "types": ["Data"], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" - }, - "data": { - "advanced": false, - "display_name": "Data", - "dynamic": false, - "info": "The data to convert to text.", - "input_types": ["Data"], - "list": true, - "name": "data", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "", - "list": false, - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template to use for formatting the data. It can contain the keys {text}, {data} or any other key in the Data.", - "input_types": ["Message"], - "list": false, - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "{text}" - } - } - }, - "type": "ParseData" - }, - "dragging": false, - "height": 302, - "id": "ParseData-BbvKb", - "measured": { - "height": 302, - "width": 320 - }, - "position": { - "x": 514.8054600415829, - "y": -117.1921617826383 - }, - "positionAbsolute": { - "x": 514.8054600415829, - "y": -117.1921617826383 - }, - "selected": false, - "type": "genericNode", - "width": 320 - }, - { - "data": { - "id": "note-e77cr", - "node": { - "description": "## Get Your OpenAI API Key\n\n**Steps**:\n\n1. **Visit** [OpenAI's API Key Page](https://platform.openai.com/api-keys).\n\n2. **Log In/Sign Up**:\n - Log in or create a new OpenAI account.\n\n3. **Generate API Key**:\n - Click \"Create New Secret Key\" to obtain your key.\n\n4. **Store Your Key Securely**:\n - Note it down as it will only display once.\n\n5. **Enter API Key**:\n - Input your key in the OpenAI API Key field within the component setup.\n\nKeep your key safe and manage it responsibly!", - "display_name": "", - "documentation": "", - "template": { - "backgroundColor": "rose" - } - }, - "type": "note" - }, - "dragging": true, - "height": 325, - "id": "note-e77cr", - "measured": { - "height": 324, - "width": 325 - }, - "position": { - "x": 1253.2038187140245, - "y": -421.5721019678553 - }, - "positionAbsolute": { - "x": 1253.2038187140245, - "y": -421.5721019678553 - }, - "selected": false, - "type": "noteNode", - "width": 325 - }, - { - "data": { - "id": "note-0kA8I", - "node": { - "description": "# Document Q&A\n\n**Purpose:**\nThis flow leverages a language model to answer questions based on content from a loaded document. It's ideal for obtaining quick insights from PDFs or other text files by asking direct questions.\n\n**Components**:\n1. **File Component**: Loads and processes your document in supported formats.\n2. **Parse Data**: Converts the loaded document into text using a specified template for consistent processing.\n3. **Prompt Component**: Forms a structured query by combining the parsed document content with user questions.\n4. **OpenAI Model**: Engages OpenAI's language model to generate responses to queries based on the document context.\n5. **Chat Input/Output**: Facilitates user queries and displays AI-generated answers seamlessly.\n\n**Steps to Use**:\n1. **Upload Document**: Use the \"File\" component to upload a document or text file you want to query.\n2. **Enter Question**: Through the \"Chat Input\" field, type your question related to the document content.\n3. **Run the Flow**: Activate the flow to process the input and generate an answer using the OpenAI model.\n4. **View Response**: Read the generated answer in the \"Chat Output\" field for immediate insights.\n\n**Benefits**:\n- Simplifies the process of extracting information from documents.\n- Provides a user-friendly interface for interactive document exploration using AI.\n", + "description": "# Document Q&A\n\nThis flow loads a file and uses an LLM to answer questions based on content from the loaded document. \n\n## Prerequisites\n\n* An [OpenAI API key](https://platform.openai.com/)\n\n## Quickstart\n\n1. Paste your OpenAI API key in the **OpenAI** model component.\n2. In the **File** component, select a file you want to load.\n3. Open the **Playground** and chat with your document.", "display_name": "", "documentation": "", "template": {} @@ -855,14 +747,14 @@ "type": "note" }, "dragging": false, - "height": 452, - "id": "note-0kA8I", + "height": 509, + "id": "note-7pTJx", "measured": { - "height": 408, - "width": 325 + "height": 509, + "width": 421 }, "position": { - "x": -338.7070086205371, + "x": -306.48794920240215, "y": -177.11912020709357 }, "positionAbsolute": { @@ -876,13 +768,15 @@ "width": 324 }, "type": "noteNode", - "width": 324 + "width": 420 }, { "data": { - "id": "File-GwJQZ", + "id": "File-3BeiJ", "node": { - "base_classes": ["Data"], + "base_classes": [ + "Data" + ], "beta": false, "conditional_paths": [], "custom_fields": {}, @@ -899,6 +793,7 @@ "frozen": false, "icon": "file-text", "legacy": false, + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -911,7 +806,9 @@ "required_inputs": [], "selected": "Data", "tool_mode": true, - "types": ["Data"], + "types": [ + "Data" + ], "value": "__UNDEFINED__" }, { @@ -923,7 +820,9 @@ "required_inputs": [], "selected": "DataFrame", "tool_mode": true, - "types": ["DataFrame"], + "types": [ + "DataFrame" + ], "value": "__UNDEFINED__" }, { @@ -935,7 +834,9 @@ "required_inputs": [], "selected": "Message", "tool_mode": true, - "types": ["Message"], + "types": [ + "Message" + ], "value": "__UNDEFINED__" } ], @@ -998,7 +899,10 @@ "display_name": "Server File Path", "dynamic": false, "info": "Data object with a 'file_path' property pointing to server file or a Message object with a path to the file. Supercedes 'Path' but supports same file types.", - "input_types": ["Data", "Message"], + "input_types": [ + "Data", + "Message" + ], "list": true, "name": "file_path", "placeholder": "", @@ -1071,7 +975,7 @@ "bz2", "gz" ], - "file_path": "", + "file_path": [], "info": "Supported file extensions: txt, md, mdx, csv, json, yaml, yml, xml, html, htm, pdf, docx, py, sh, sql, js, ts, tsx; optionally bundled in file extensions: zip, tar, tgz, bz2, gz", "list": true, "name": "path", @@ -1141,7 +1045,7 @@ }, "dragging": false, "height": 232, - "id": "File-GwJQZ", + "id": "File-3BeiJ", "measured": { "height": 232, "width": 320 @@ -1162,20 +1066,26 @@ "data": { "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", - "id": "Prompt-yvZHT", + "id": "Prompt-yAr8f", "node": { - "base_classes": ["Message"], + "base_classes": [ + "Message" + ], "beta": false, "conditional_paths": [], "custom_fields": { - "template": ["Document"] + "template": [ + "Document" + ] }, "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", "documentation": "", "edited": false, "error": null, - "field_order": ["template"], + "field_order": [ + "template" + ], "frozen": false, "full_path": null, "icon": "prompts", @@ -1196,7 +1106,9 @@ "name": "prompt", "selected": "Message", "tool_mode": true, - "types": ["Message"], + "types": [ + "Message" + ], "value": "__UNDEFINED__" } ], @@ -1210,7 +1122,10 @@ "fileTypes": [], "file_path": "", "info": "", - "input_types": ["Message", "Text"], + "input_types": [ + "Message", + "Text" + ], "list": false, "load_from_db": false, "multiline": true, @@ -1263,7 +1178,9 @@ "display_name": "Tool Placeholder", "dynamic": false, "info": "A placeholder input for tool mode.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "tool_placeholder", @@ -1284,7 +1201,7 @@ }, "dragging": false, "height": 347, - "id": "Prompt-yvZHT", + "id": "Prompt-yAr8f", "measured": { "height": 347, "width": 320 @@ -1303,9 +1220,12 @@ }, { "data": { - "id": "OpenAIModel-atkmo", + "id": "OpenAIModel-Xctjl", "node": { - "base_classes": ["LanguageModel", "Message"], + "base_classes": [ + "LanguageModel", + "Message" + ], "beta": false, "category": "models", "conditional_paths": [], @@ -1344,7 +1264,9 @@ "required_inputs": [], "selected": "Message", "tool_mode": true, - "types": ["Message"], + "types": [ + "Message" + ], "value": "__UNDEFINED__" }, { @@ -1353,10 +1275,14 @@ "display_name": "Language Model", "method": "build_model", "name": "model_output", - "required_inputs": ["api_key"], + "required_inputs": [ + "api_key" + ], "selected": "LanguageModel", "tool_mode": true, - "types": ["LanguageModel"], + "types": [ + "LanguageModel" + ], "value": "__UNDEFINED__" } ], @@ -1370,7 +1296,9 @@ "display_name": "OpenAI API Key", "dynamic": false, "info": "The OpenAI API Key to use for the OpenAI model.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "load_from_db": true, "name": "api_key", "password": true, @@ -1379,7 +1307,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -1405,7 +1333,9 @@ "display_name": "Input", "dynamic": false, "info": "", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "list_add_label": "Add More", "load_from_db": false, @@ -1587,7 +1517,9 @@ "display_name": "System Message", "dynamic": false, "info": "System message to pass to the model.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "list_add_label": "Add More", "load_from_db": false, @@ -1656,9 +1588,9 @@ "type": "OpenAIModel" }, "dragging": false, - "id": "OpenAIModel-atkmo", + "id": "OpenAIModel-Xctjl", "measured": { - "height": 653, + "height": 525, "width": 320 }, "position": { @@ -1667,21 +1599,197 @@ }, "selected": false, "type": "genericNode" + }, + { + "data": { + "id": "parser-mO32W", + "node": { + "base_classes": [ + "Message" + ], + "beta": false, + "category": "processing", + "conditional_paths": [], + "custom_fields": {}, + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", + "documentation": "", + "edited": false, + "field_order": [ + "mode", + "pattern", + "input_data", + "sep" + ], + "frozen": false, + "icon": "braces", + "key": "parser", + "legacy": false, + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", + "selected": "Message", + "tool_mode": true, + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 2.220446049250313e-16, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n name = \"parser\"\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" + }, + "input_data": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Data or DataFrame", + "dynamic": false, + "info": "Accepts either a DataFrame or a Data object.", + "input_types": [ + "DataFrame", + "Data" + ], + "list": false, + "list_add_label": "Add More", + "name": "input_data", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Parser" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "Text: {text}" + }, + "sep": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Separator", + "dynamic": false, + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "sep", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "\n" + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "parser" + }, + "dragging": false, + "id": "parser-mO32W", + "measured": { + "height": 395, + "width": 320 + }, + "position": { + "x": 517.4341822104063, + "y": -211.09448665229442 + }, + "selected": true, + "type": "genericNode" } ], "viewport": { - "x": 285.05178335748246, - "y": 410.84335125276027, - "zoom": 0.6261967792362849 + "x": 201.52975647724884, + "y": 410.819941953365, + "zoom": 0.6386710713834723 } }, "description": "Integrates PDF reading with a language model to answer document-specific questions. Ideal for small-scale texts, it facilitates direct queries with immediate insights.", "endpoint_name": null, - "gradient": "3", - "icon": "FileQuestion", - "id": "febba2f9-69b3-484b-8aef-65626810ec8a", + "id": "e088aa15-23da-4839-b3f0-eb733b973a8b", "is_component": false, - "last_tested_version": "1.0.19.post2", + "last_tested_version": "1.2.0", "name": "Document Q&A", - "tags": ["rag", "q-a", "openai"] -} + "tags": [ + "rag", + "q-a", + "openai" + ] +} \ No newline at end of file diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json b/src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json index 910582126..28f32071f 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json @@ -7,7 +7,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-nRbVG", + "id": "OpenAIModel-7hzeM", "name": "model_output", "output_types": [ "LanguageModel" @@ -15,19 +15,19 @@ }, "targetHandle": { "fieldName": "llm", - "id": "StructuredOutput-KQHp8", + "id": "StructuredOutput-XPbNI", "inputTypes": [ "LanguageModel" ], "type": "other" } }, - "id": "reactflow__edge-OpenAIModel-nRbVG{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-nRbVGœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutput-KQHp8{œfieldNameœ:œllmœ,œidœ:œStructuredOutput-KQHp8œ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-OpenAIModel-7hzeM{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-7hzeMœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutput-XPbNI{œfieldNameœ:œllmœ,œidœ:œStructuredOutput-XPbNIœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", "selected": false, - "source": "OpenAIModel-nRbVG", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-nRbVGœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", - "target": "StructuredOutput-KQHp8", - "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œStructuredOutput-KQHp8œ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" + "source": "OpenAIModel-7hzeM", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-7hzeMœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", + "target": "StructuredOutput-XPbNI", + "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œStructuredOutput-XPbNIœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -35,7 +35,7 @@ "data": { "sourceHandle": { "dataType": "ChatInput", - "id": "ChatInput-dq6uf", + "id": "ChatInput-dKvV3", "name": "message", "output_types": [ "Message" @@ -43,35 +43,61 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "StructuredOutput-KQHp8", + "id": "StructuredOutput-XPbNI", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-ChatInput-dq6uf{œdataTypeœ:œChatInputœ,œidœ:œChatInput-dq6ufœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-StructuredOutput-KQHp8{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutput-KQHp8œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-dKvV3{œdataTypeœ:œChatInputœ,œidœ:œChatInput-dKvV3œ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-StructuredOutput-XPbNI{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutput-XPbNIœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "ChatInput-dq6uf", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-dq6ufœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "StructuredOutput-KQHp8", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œStructuredOutput-KQHp8œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "ChatInput-dKvV3", + "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-dKvV3œ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "StructuredOutput-XPbNI", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œStructuredOutput-XPbNIœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, - "className": "", "data": { "sourceHandle": { - "dataType": "ParseDataFrame", - "id": "ParseDataFrame-QOEC3", - "name": "text", + "dataType": "StructuredOutput", + "id": "StructuredOutput-XPbNI", + "name": "structured_output_dataframe", + "output_types": [ + "DataFrame" + ] + }, + "targetHandle": { + "fieldName": "input_data", + "id": "parser-s4Kz6", + "inputTypes": [ + "DataFrame", + "Data" + ], + "type": "other" + } + }, + "id": "xy-edge__StructuredOutput-XPbNI{œdataTypeœ:œStructuredOutputœ,œidœ:œStructuredOutput-XPbNIœ,œnameœ:œstructured_output_dataframeœ,œoutput_typesœ:[œDataFrameœ]}-parser-s4Kz6{œfieldNameœ:œinput_dataœ,œidœ:œparser-s4Kz6œ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", + "selected": false, + "source": "StructuredOutput-XPbNI", + "sourceHandle": "{œdataTypeœ: œStructuredOutputœ, œidœ: œStructuredOutput-XPbNIœ, œnameœ: œstructured_output_dataframeœ, œoutput_typesœ: [œDataFrameœ]}", + "target": "parser-s4Kz6", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-s4Kz6œ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" + }, + { + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-s4Kz6", + "name": "parsed_text", "output_types": [ "Message" ] }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-BNHyf", + "id": "ChatOutput-meCWe", "inputTypes": [ "Data", "DataFrame", @@ -80,46 +106,17 @@ "type": "str" } }, - "id": "reactflow__edge-ParseDataFrame-QOEC3{œdataTypeœ:œParseDataFrameœ,œidœ:œParseDataFrame-QOEC3œ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-BNHyf{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-BNHyfœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseDataFrame-QOEC3", - "sourceHandle": "{œdataTypeœ: œParseDataFrameœ, œidœ: œParseDataFrame-QOEC3œ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-BNHyf", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-BNHyfœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "StructuredOutput", - "id": "StructuredOutput-KQHp8", - "name": "structured_output_dataframe", - "output_types": [ - "DataFrame" - ] - }, - "targetHandle": { - "fieldName": "df", - "id": "ParseDataFrame-QOEC3", - "inputTypes": [ - "DataFrame" - ], - "type": "other" - } - }, - "id": "reactflow__edge-StructuredOutput-KQHp8{œdataTypeœ:œStructuredOutputœ,œidœ:œStructuredOutput-KQHp8œ,œnameœ:œstructured_output_dataframeœ,œoutput_typesœ:[œDataFrameœ]}-ParseDataFrame-QOEC3{œfieldNameœ:œdfœ,œidœ:œParseDataFrame-QOEC3œ,œinputTypesœ:[œDataFrameœ],œtypeœ:œotherœ}", - "selected": false, - "source": "StructuredOutput-KQHp8", - "sourceHandle": "{œdataTypeœ: œStructuredOutputœ, œidœ: œStructuredOutput-KQHp8œ, œnameœ: œstructured_output_dataframeœ, œoutput_typesœ: [œDataFrameœ]}", - "target": "ParseDataFrame-QOEC3", - "targetHandle": "{œfieldNameœ: œdfœ, œidœ: œParseDataFrame-QOEC3œ, œinputTypesœ: [œDataFrameœ], œtypeœ: œotherœ}" + "id": "xy-edge__parser-s4Kz6{œdataTypeœ:œparserœ,œidœ:œparser-s4Kz6œ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-meCWe{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-meCWeœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "source": "parser-s4Kz6", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-s4Kz6œ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-meCWe", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-meCWeœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" } ], "nodes": [ { "data": { - "id": "OpenAIModel-nRbVG", + "id": "OpenAIModel-7hzeM", "node": { "base_classes": [ "LanguageModel", @@ -152,7 +149,7 @@ "icon": "OpenAI", "key": "OpenAIModel", "legacy": false, - "lf_version": "1.1.5", + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -209,7 +206,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -490,7 +487,7 @@ "type": "OpenAIModel" }, "dragging": false, - "id": "OpenAIModel-nRbVG", + "id": "OpenAIModel-7hzeM", "measured": { "height": 525, "width": 320 @@ -504,7 +501,7 @@ }, { "data": { - "id": "ChatOutput-BNHyf", + "id": "ChatOutput-meCWe", "node": { "base_classes": [ "Message" @@ -532,7 +529,7 @@ "icon": "MessagesSquare", "key": "ChatOutput", "legacy": false, - "lf_version": "1.1.5", + "lf_version": "1.2.0", "metadata": {}, "minimized": true, "output_types": [], @@ -801,7 +798,7 @@ "showNode": false, "type": "ChatOutput" }, - "id": "ChatOutput-BNHyf", + "id": "ChatOutput-meCWe", "measured": { "height": 66, "width": 192 @@ -815,7 +812,7 @@ }, { "data": { - "id": "ChatInput-dq6uf", + "id": "ChatInput-dKvV3", "node": { "base_classes": [ "Message" @@ -843,7 +840,7 @@ "icon": "MessagesSquare", "key": "ChatInput", "legacy": false, - "lf_version": "1.1.5", + "lf_version": "1.2.0", "metadata": {}, "minimized": true, "output_types": [], @@ -1113,7 +1110,7 @@ "type": "ChatInput" }, "dragging": false, - "id": "ChatInput-dq6uf", + "id": "ChatInput-dKvV3", "measured": { "height": 66, "width": 192 @@ -1127,7 +1124,7 @@ }, { "data": { - "id": "note-lPaVF", + "id": "note-noWIg", "node": { "description": "### 💡 Add your OpenAI API key here", "display_name": "", @@ -1139,7 +1136,7 @@ "type": "note" }, "dragging": false, - "id": "note-lPaVF", + "id": "note-noWIg", "measured": { "height": 324, "width": 324 @@ -1153,7 +1150,7 @@ }, { "data": { - "id": "note-OrB5w", + "id": "note-1vbDd", "node": { "description": "\n# Financial Report Parser\n\nThis template extracts key financial metrics from a given financial report text using OpenAI's GPT-4o-mini model. The extracted data is structured and formatted for chat consumption.\n\n## Prerequisites\n\n- **[OpenAI API Key](https://platform.openai.com/)**\n\n## Quickstart\n\n1. Add your OpenAI API key to the OpenAI model.\n2. To run the flow, click **Playground**.\nThe **Chat Input** component in this template is pre-loaded with a sample financial report for demonstrating how structured data is extracted.\n\n* The **OpenAI** model component identifies and retrieves Gross Profit, EBITDA, Net Income, and Operating Expenses from the financial report.\n* The **Structured Output** component formats extracted data into a structured format for better readability and further processing.\n* The **Data to Message** component converts extracted data into formatted messages for chat consumption.\n\n\n\n\n\n", "display_name": "", @@ -1164,7 +1161,7 @@ }, "dragging": false, "height": 688, - "id": "note-OrB5w", + "id": "note-1vbDd", "measured": { "height": 688, "width": 620 @@ -1180,7 +1177,7 @@ }, { "data": { - "id": "StructuredOutput-KQHp8", + "id": "StructuredOutput-XPbNI", "node": { "base_classes": [ "Data", @@ -1203,6 +1200,7 @@ "frozen": false, "icon": "braces", "legacy": false, + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -1467,7 +1465,7 @@ "type": "StructuredOutput" }, "dragging": false, - "id": "StructuredOutput-KQHp8", + "id": "StructuredOutput-XPbNI", "measured": { "height": 447, "width": 320 @@ -1481,7 +1479,7 @@ }, { "data": { - "id": "ParseDataFrame-QOEC3", + "id": "parser-s4Kz6", "node": { "base_classes": [ "Message" @@ -1490,20 +1488,20 @@ "category": "processing", "conditional_paths": [], "custom_fields": {}, - "description": "Convert a DataFrame into plain text following a specified template. Each column in the DataFrame is treated as a possible template key, e.g. {col_name}.", - "display_name": "Parse DataFrame", + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", "documentation": "", "edited": false, "field_order": [ - "df", - "template", + "mode", + "pattern", + "input_data", "sep" ], "frozen": false, "icon": "braces", - "key": "ParseDataFrame", + "key": "parser", "legacy": false, - "lf_version": "1.1.5", "metadata": {}, "minimized": false, "output_types": [], @@ -1511,9 +1509,9 @@ { "allows_loop": false, "cache": true, - "display_name": "Text", - "method": "parse_data", - "name": "text", + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", "selected": "Message", "tool_mode": true, "types": [ @@ -1523,7 +1521,7 @@ } ], "pinned": false, - "score": 0.007568328950209746, + "score": 2.220446049250313e-16, "template": { "_type": "Component", "code": { @@ -1542,36 +1540,84 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.io import DataFrameInput, MultilineInput, Output, StrInput\nfrom langflow.schema.message import Message\n\n\nclass ParseDataFrameComponent(Component):\n display_name = \"Parse DataFrame\"\n description = (\n \"Convert a DataFrame into plain text following a specified template. \"\n \"Each column in the DataFrame is treated as a possible template key, e.g. {col_name}.\"\n )\n icon = \"braces\"\n name = \"ParseDataFrame\"\n\n inputs = [\n DataFrameInput(name=\"df\", display_name=\"DataFrame\", info=\"The DataFrame to convert to text rows.\"),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=(\n \"The template for formatting each row. \"\n \"Use placeholders matching column names in the DataFrame, for example '{col1}', '{col2}'.\"\n ),\n value=\"{text}\",\n ),\n StrInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String that joins all row texts when building the single Text output.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Text\",\n name=\"text\",\n info=\"All rows combined into a single text, each row formatted by the template and separated by `sep`.\",\n method=\"parse_data\",\n ),\n ]\n\n def _clean_args(self):\n dataframe = self.df\n template = self.template or \"{text}\"\n sep = self.sep or \"\\n\"\n return dataframe, template, sep\n\n def parse_data(self) -> Message:\n \"\"\"Converts each row of the DataFrame into a formatted string using the template.\n\n then joins them with `sep`. Returns a single combined string as a Message.\n \"\"\"\n dataframe, template, sep = self._clean_args()\n\n lines = []\n # For each row in the DataFrame, build a dict and format\n for _, row in dataframe.iterrows():\n row_dict = row.to_dict()\n text_line = template.format(**row_dict) # e.g. template=\"{text}\", row_dict={\"text\": \"Hello\"}\n lines.append(text_line)\n\n # Join all lines with the provided separator\n result_string = sep.join(lines)\n self.status = result_string # store in self.status for UI logs\n return Message(text=result_string)\n" + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n name = \"parser\"\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" }, - "df": { - "_input_type": "DataFrameInput", + "input_data": { + "_input_type": "HandleInput", "advanced": false, - "display_name": "DataFrame", + "display_name": "Data or DataFrame", "dynamic": false, - "info": "The DataFrame to convert to text rows.", + "info": "Accepts either a DataFrame or a Data object.", "input_types": [ - "DataFrame" + "DataFrame", + "Data" ], "list": false, "list_add_label": "Add More", - "name": "df", + "name": "input_data", "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, "required": false, "show": true, "title_case": false, "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Parser" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, - "type": "other", - "value": "" + "type": "str", + "value": "EBITIDA: {EBITIDA} , Net Income: {NET_INCOME} , GROSS_PROFIT: {GROSS_PROFIT}" }, "sep": { - "_input_type": "StrInput", + "_input_type": "MessageTextInput", "advanced": true, "display_name": "Separator", "dynamic": false, - "info": "String that joins all row texts when building the single Text output.", + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], "list": false, "list_add_label": "Add More", "load_from_db": false, @@ -1581,63 +1627,40 @@ "show": true, "title_case": false, "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "_input_type": "MultilineInput", - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template for formatting each row. Use placeholders matching column names in the DataFrame, for example '{col1}', '{col2}'.", - "input_types": [ - "Message" - ], - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, "trace_as_input": true, "trace_as_metadata": true, "type": "str", - "value": "EBITIDA: {EBITIDA} , Net Income: {NET_INCOME} , GROSS_PROFIT: {GROSS_PROFIT}" + "value": "\n" } }, "tool_mode": false }, "showNode": true, - "type": "ParseDataFrame" + "type": "parser" }, "dragging": false, - "id": "ParseDataFrame-QOEC3", + "id": "parser-s4Kz6", "measured": { - "height": 334, + "height": 395, "width": 320 }, "position": { - "x": 1783.5562660355338, - "y": 269.9258338477598 + "x": 1765.290752395121, + "y": 164.78283431885177 }, - "selected": false, + "selected": true, "type": "genericNode" } ], "viewport": { - "x": -99.6371290033394, - "y": 399.2977275294001, - "zoom": 0.6105558084817295 + "x": -17.069750343754663, + "y": 450.3545210238955, + "zoom": 0.5500905440229726 } }, "description": "Extracts key financial metrics like Gross Profit, EBITDA, and Net Income from financial reports and structures them for easy analysis, using Structured Output Component", "endpoint_name": null, - "id": "a217ddf6-8620-4f38-ac09-5b35f612ce9e", + "id": "43308dc6-b08e-4366-8fac-18cee79db1c5", "is_component": false, "last_tested_version": "1.2.0", "name": "Financial Report Parser", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json b/src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json index f51d2a249..e79aef8e2 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json @@ -6,140 +6,171 @@ "className": "", "data": { "sourceHandle": { - "dataType": "StructuredOutputComponent", - "id": "StructuredOutputComponent-XYoUc", - "name": "structured_output", - "output_types": ["Data"] + "dataType": "ChatInput", + "id": "ChatInput-nHfqr", + "name": "message", + "output_types": [ + "Message" + ] }, "targetHandle": { - "fieldName": "data", - "id": "ParseData-HzweJ", - "inputTypes": ["Data"], - "type": "other" + "fieldName": "input_value", + "id": "OpenAIModel-S4vrc", + "inputTypes": [ + "Message" + ], + "type": "str" } }, - "id": "reactflow__edge-StructuredOutputComponent-XYoUc{œdataTypeœ:œStructuredOutputComponentœ,œidœ:œStructuredOutputComponent-XYoUcœ,œnameœ:œstructured_outputœ,œoutput_typesœ:[œDataœ]}-ParseData-HzweJ{œfieldNameœ:œdataœ,œidœ:œParseData-HzweJœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-ChatInput-nHfqr{œdataTypeœ:œChatInputœ,œidœ:œChatInput-nHfqrœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-S4vrc{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-S4vrcœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "StructuredOutputComponent-XYoUc", - "sourceHandle": "{œdataTypeœ: œStructuredOutputComponentœ, œidœ: œStructuredOutputComponent-XYoUcœ, œnameœ: œstructured_outputœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-HzweJ", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-HzweJœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" + "source": "ChatInput-nHfqr", + "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-nHfqrœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-S4vrc", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-S4vrcœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-HzweJ", - "name": "text", - "output_types": ["Message"] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "ChatOutput-xQxLm", - "inputTypes": ["Data", "DataFrame", "Message"], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-HzweJ{œdataTypeœ:œParseDataœ,œidœ:œParseData-HzweJœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-xQxLm{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-xQxLmœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-HzweJ", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-HzweJœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-xQxLm", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-xQxLmœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" - }, - { - "className": "", - "data": { - "sourceHandle": { - "dataType": "ChatInput", - "id": "ChatInput-rAWlE", - "name": "message", - "output_types": ["Message"] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "OpenAIModel-cqeNw", - "inputTypes": ["Message"], - "type": "str" - } - }, - "id": "reactflow__edge-ChatInput-rAWlE{œdataTypeœ:œChatInputœ,œidœ:œChatInput-rAWlEœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-cqeNw{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-cqeNwœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ChatInput-rAWlE", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-rAWlEœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-cqeNw", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-cqeNwœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { "className": "", "data": { "sourceHandle": { "dataType": "Prompt", - "id": "Prompt-AzK6t", + "id": "Prompt-j1IvC", "name": "prompt", - "output_types": ["Message"] + "output_types": [ + "Message" + ] }, "targetHandle": { "fieldName": "system_message", - "id": "OpenAIModel-cqeNw", - "inputTypes": ["Message"], + "id": "OpenAIModel-S4vrc", + "inputTypes": [ + "Message" + ], "type": "str" } }, - "id": "reactflow__edge-Prompt-AzK6t{œdataTypeœ:œPromptœ,œidœ:œPrompt-AzK6tœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-cqeNw{œfieldNameœ:œsystem_messageœ,œidœ:œOpenAIModel-cqeNwœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-j1IvC{œdataTypeœ:œPromptœ,œidœ:œPrompt-j1IvCœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-S4vrc{œfieldNameœ:œsystem_messageœ,œidœ:œOpenAIModel-S4vrcœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Prompt-AzK6t", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-AzK6tœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-cqeNw", - "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œOpenAIModel-cqeNwœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "Prompt-j1IvC", + "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-j1IvCœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-S4vrc", + "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œOpenAIModel-S4vrcœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { + "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-cqeNw", - "name": "text_output", - "output_types": ["Message"] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "StructuredOutputComponent-XYoUc", - "inputTypes": ["Message"], - "type": "str" - } - }, - "id": "reactflow__edge-OpenAIModel-cqeNw{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-cqeNwœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-StructuredOutputComponent-XYoUc{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutputComponent-XYoUcœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "OpenAIModel-cqeNw", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-cqeNwœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "StructuredOutputComponent-XYoUc", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œStructuredOutputComponent-XYoUcœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "className": "", - "data": { - "sourceHandle": { - "dataType": "OpenAIModel", - "id": "OpenAIModel-cqeNw", + "id": "OpenAIModel-S4vrc", "name": "model_output", - "output_types": ["LanguageModel"] + "output_types": [ + "LanguageModel" + ] }, "targetHandle": { "fieldName": "llm", - "id": "StructuredOutputComponent-XYoUc", - "inputTypes": ["LanguageModel"], + "id": "StructuredOutput-jrD6H", + "inputTypes": [ + "LanguageModel" + ], "type": "other" } }, - "id": "reactflow__edge-OpenAIModel-cqeNw{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-cqeNwœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutputComponent-XYoUc{œfieldNameœ:œllmœ,œidœ:œStructuredOutputComponent-XYoUcœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-OpenAIModel-S4vrc{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-S4vrcœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutput-jrD6H{œfieldNameœ:œllmœ,œidœ:œStructuredOutput-jrD6Hœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", "selected": false, - "source": "OpenAIModel-cqeNw", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-cqeNwœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", - "target": "StructuredOutputComponent-XYoUc", - "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œStructuredOutputComponent-XYoUcœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" + "source": "OpenAIModel-S4vrc", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-S4vrcœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", + "target": "StructuredOutput-jrD6H", + "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œStructuredOutput-jrD6Hœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "OpenAIModel", + "id": "OpenAIModel-S4vrc", + "name": "text_output", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "StructuredOutput-jrD6H", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-OpenAIModel-S4vrc{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-S4vrcœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-StructuredOutput-jrD6H{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutput-jrD6Hœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "OpenAIModel-S4vrc", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-S4vrcœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "StructuredOutput-jrD6H", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œStructuredOutput-jrD6Hœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "StructuredOutput", + "id": "StructuredOutput-jrD6H", + "name": "structured_output_dataframe", + "output_types": [ + "DataFrame" + ] + }, + "targetHandle": { + "fieldName": "input_data", + "id": "parser-IVklX", + "inputTypes": [ + "DataFrame", + "Data" + ], + "type": "other" + } + }, + "id": "xy-edge__StructuredOutput-jrD6H{œdataTypeœ:œStructuredOutputœ,œidœ:œStructuredOutput-jrD6Hœ,œnameœ:œstructured_output_dataframeœ,œoutput_typesœ:[œDataFrameœ]}-parser-IVklX{œfieldNameœ:œinput_dataœ,œidœ:œparser-IVklXœ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", + "selected": false, + "source": "StructuredOutput-jrD6H", + "sourceHandle": "{œdataTypeœ: œStructuredOutputœ, œidœ: œStructuredOutput-jrD6Hœ, œnameœ: œstructured_output_dataframeœ, œoutput_typesœ: [œDataFrameœ]}", + "target": "parser-IVklX", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-IVklXœ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-IVklX", + "name": "parsed_text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-gjqnD", + "inputTypes": [ + "Data", + "DataFrame", + "Message" + ], + "type": "str" + } + }, + "id": "xy-edge__parser-IVklX{œdataTypeœ:œparserœ,œidœ:œparser-IVklXœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-gjqnD{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-gjqnDœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "parser-IVklX", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-IVklXœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-gjqnD", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-gjqnDœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" } ], "nodes": [ @@ -147,9 +178,11 @@ "data": { "description": "Get chat inputs from the Playground.", "display_name": "Chat Input", - "id": "ChatInput-rAWlE", + "id": "ChatInput-nHfqr", "node": { - "base_classes": ["Message"], + "base_classes": [ + "Message" + ], "beta": false, "conditional_paths": [], "custom_fields": {}, @@ -171,7 +204,7 @@ "frozen": false, "icon": "MessagesSquare", "legacy": false, - "lf_version": "1.0.19.post2", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -183,7 +216,9 @@ "name": "message", "selected": "Message", "tool_mode": true, - "types": ["Message"], + "types": [ + "Message" + ], "value": "__UNDEFINED__" } ], @@ -196,7 +231,9 @@ "display_name": "Background Color", "dynamic": false, "info": "The background color of the icon.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "background_color", @@ -216,7 +253,9 @@ "display_name": "Icon", "dynamic": false, "info": "The icon of the message.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "chat_icon", @@ -320,7 +359,10 @@ "dynamic": false, "info": "Type of sender.", "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "placeholder": "", "required": false, "show": true, @@ -336,7 +378,9 @@ "display_name": "Sender Name", "dynamic": false, "info": "Name of the sender.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "sender_name", @@ -356,7 +400,9 @@ "display_name": "Session ID", "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "session_id", @@ -392,7 +438,9 @@ "display_name": "Text Color", "dynamic": false, "info": "The text color of the name", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "text_color", @@ -413,7 +461,7 @@ }, "dragging": false, "height": 234, - "id": "ChatInput-rAWlE", + "id": "ChatInput-nHfqr", "measured": { "height": 234, "width": 320 @@ -434,9 +482,11 @@ "data": { "description": "Display a chat message in the Playground.", "display_name": "Chat Output", - "id": "ChatOutput-xQxLm", + "id": "ChatOutput-gjqnD", "node": { - "base_classes": ["Message"], + "base_classes": [ + "Message" + ], "beta": false, "conditional_paths": [], "custom_fields": {}, @@ -458,7 +508,7 @@ "frozen": false, "icon": "MessagesSquare", "legacy": false, - "lf_version": "1.0.19.post2", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -470,7 +520,9 @@ "name": "message", "selected": "Message", "tool_mode": true, - "types": ["Message"], + "types": [ + "Message" + ], "value": "__UNDEFINED__" } ], @@ -483,7 +535,9 @@ "display_name": "Background Color", "dynamic": false, "info": "The background color of the icon.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "background_color", @@ -503,7 +557,9 @@ "display_name": "Icon", "dynamic": false, "info": "The icon of the message.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "chat_icon", @@ -559,7 +615,9 @@ "display_name": "Data Template", "dynamic": false, "info": "Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "data_template", @@ -579,7 +637,11 @@ "display_name": "Text", "dynamic": false, "info": "Message to be passed as output.", - "input_types": ["Data", "DataFrame", "Message"], + "input_types": [ + "Data", + "DataFrame", + "Message" + ], "list": false, "load_from_db": false, "name": "input_value", @@ -600,7 +662,10 @@ "dynamic": false, "info": "Type of sender.", "name": "sender", - "options": ["Machine", "User"], + "options": [ + "Machine", + "User" + ], "placeholder": "", "required": false, "show": true, @@ -616,7 +681,9 @@ "display_name": "Sender Name", "dynamic": false, "info": "Name of the sender.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "sender_name", @@ -636,7 +703,9 @@ "display_name": "Session ID", "dynamic": false, "info": "The session ID of the chat. If empty, the current session ID parameter will be used.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "session_id", @@ -672,7 +741,9 @@ "display_name": "Text Color", "dynamic": false, "info": "The text color of the name", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "text_color", @@ -693,7 +764,7 @@ }, "dragging": false, "height": 234, - "id": "ChatOutput-xQxLm", + "id": "ChatOutput-gjqnD", "measured": { "height": 234, "width": 320 @@ -712,7 +783,7 @@ }, { "data": { - "id": "note-K9w8w", + "id": "note-jDost", "node": { "description": "# Image Sentiment Analysis\nWelcome to the Image Sentiment Classifier - an AI tool for quick image sentiment analysis!\n\n## Instructions\n\n1. **Prepare Your Image**\n - Image should be clear and visible\n\n2. **Upload Options**\n - Open the Playground\n - Click file attachment icon\n - Or drag and drop into playground\n\n3. **Wait for Analysis**\n - System will process the image\n - Uses zero-shot learning\n - Classification happens automatically\n\n4. **Review Results**\n - Get classification: Positive/Negative/Neutral\n - Review confidence level\n - Check reasoning if provided\n\n5. **Expected Classifications**\n - Positive: Happy scenes, smiles, celebrations\n - Negative: Sad scenes, problems, conflicts\n - Neutral: Objects, landscapes, neutral scenes\n\nRemember: The clearer the image, the more accurate the classification! 📸✨", "display_name": "", @@ -723,9 +794,9 @@ }, "dragging": false, "height": 583, - "id": "note-K9w8w", + "id": "note-jDost", "measured": { - "height": 570, + "height": 583, "width": 325 }, "position": { @@ -745,385 +816,15 @@ "type": "noteNode", "width": 324 }, - { - "data": { - "description": "Transforms LLM responses into **structured data formats**. Ideal for extracting specific information or creating consistent outputs.", - "display_name": "Structured Output", - "id": "StructuredOutputComponent-XYoUc", - "node": { - "base_classes": ["Data"], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "Transforms LLM responses into **structured data formats**. Ideal for extracting specific information or creating consistent outputs.", - "display_name": "Structured Output", - "documentation": "", - "edited": false, - "field_order": [ - "llm", - "input_value", - "schema_name", - "output_schema", - "multiple" - ], - "frozen": false, - "icon": "braces", - "legacy": false, - "lf_version": "1.0.19.post2", - "metadata": {}, - "output_types": [], - "outputs": [ - { - "cache": true, - "display_name": "Structured Output", - "method": "build_structured_output", - "name": "structured_output", - "selected": "Data", - "types": ["Data"], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from typing import TYPE_CHECKING, cast\n\nfrom pydantic import BaseModel, Field, create_model\n\nfrom langflow.base.models.chat_result import get_chat_result\nfrom langflow.custom import Component\nfrom langflow.helpers.base_model import build_model_from_schema\nfrom langflow.io import BoolInput, HandleInput, MessageTextInput, Output, StrInput, TableInput\nfrom langflow.schema.data import Data\n\nif TYPE_CHECKING:\n from langflow.field_typing.constants import LanguageModel\n\n\nclass StructuredOutputComponent(Component):\n display_name = \"Structured Output\"\n description = (\n \"Transforms LLM responses into **structured data formats**. Ideal for extracting specific information \"\n \"or creating consistent outputs.\"\n )\n icon = \"braces\"\n\n inputs = [\n HandleInput(\n name=\"llm\",\n display_name=\"Language Model\",\n info=\"The language model to use to generate the structured output.\",\n input_types=[\"LanguageModel\"],\n ),\n MessageTextInput(name=\"input_value\", display_name=\"Input message\"),\n StrInput(\n name=\"schema_name\",\n display_name=\"Schema Name\",\n info=\"Provide a name for the output data schema.\",\n ),\n TableInput(\n name=\"output_schema\",\n display_name=\"Output Schema\",\n info=\"Define the structure and data types for the model's output.\",\n table_schema=[\n {\n \"name\": \"name\",\n \"display_name\": \"Name\",\n \"type\": \"str\",\n \"description\": \"Specify the name of the output field.\",\n \"default\": \"field\",\n },\n {\n \"name\": \"description\",\n \"display_name\": \"Description\",\n \"type\": \"str\",\n \"description\": \"Describe the purpose of the output field.\",\n \"default\": \"description of field\",\n },\n {\n \"name\": \"type\",\n \"display_name\": \"Type\",\n \"type\": \"str\",\n \"description\": (\n \"Indicate the data type of the output field (e.g., str, int, float, bool, list, dict).\"\n ),\n \"default\": \"text\",\n },\n {\n \"name\": \"multiple\",\n \"display_name\": \"Multiple\",\n \"type\": \"boolean\",\n \"description\": \"Set to True if this output field should be a list of the specified type.\",\n \"default\": \"False\",\n },\n ],\n value=[{\"name\": \"field\", \"description\": \"description of field\", \"type\": \"text\", \"multiple\": \"False\"}],\n ),\n BoolInput(\n name=\"multiple\",\n display_name=\"Generate Multiple\",\n info=\"Set to True if the model should generate a list of outputs instead of a single output.\",\n ),\n ]\n\n outputs = [\n Output(name=\"structured_output\", display_name=\"Structured Output\", method=\"build_structured_output\"),\n ]\n\n def build_structured_output(self) -> Data:\n if not hasattr(self.llm, \"with_structured_output\"):\n msg = \"Language model does not support structured output.\"\n raise TypeError(msg)\n if not self.output_schema:\n msg = \"Output schema cannot be empty\"\n raise ValueError(msg)\n\n output_model_ = build_model_from_schema(self.output_schema)\n if self.multiple:\n output_model = create_model(\n self.schema_name,\n objects=(list[output_model_], Field(description=f\"A list of {self.schema_name}.\")), # type: ignore[valid-type]\n )\n else:\n output_model = output_model_\n try:\n llm_with_structured_output = cast(\"LanguageModel\", self.llm).with_structured_output(schema=output_model) # type: ignore[valid-type, attr-defined]\n\n except NotImplementedError as exc:\n msg = f\"{self.llm.__class__.__name__} does not support structured output.\"\n raise TypeError(msg) from exc\n config_dict = {\n \"run_name\": self.display_name,\n \"project_name\": self.get_project_name(),\n \"callbacks\": self.get_langchain_callbacks(),\n }\n output = get_chat_result(runnable=llm_with_structured_output, input_value=self.input_value, config=config_dict)\n if isinstance(output, BaseModel):\n output_dict = output.model_dump()\n else:\n msg = f\"Output should be a Pydantic BaseModel, got {type(output)} ({output})\"\n raise TypeError(msg)\n return Data(data=output_dict)\n" - }, - "input_value": { - "_input_type": "MessageTextInput", - "advanced": false, - "display_name": "Input message", - "dynamic": false, - "info": "", - "input_types": ["Message"], - "list": false, - "load_from_db": false, - "name": "input_value", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "" - }, - "llm": { - "_input_type": "HandleInput", - "advanced": false, - "display_name": "Language Model", - "dynamic": false, - "info": "The language model to use to generate the structured output.", - "input_types": ["LanguageModel"], - "list": false, - "name": "llm", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "multiple": { - "_input_type": "BoolInput", - "advanced": false, - "display_name": "Generate Multiple", - "dynamic": false, - "info": "Set to True if the model should generate a list of outputs instead of a single output.", - "list": false, - "name": "multiple", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "bool", - "value": false - }, - "output_schema": { - "_input_type": "TableInput", - "advanced": false, - "display_name": "Output Schema", - "dynamic": false, - "info": "Define the structure and data types for the model's output.", - "is_list": true, - "load_from_db": false, - "name": "output_schema", - "placeholder": "", - "required": false, - "show": true, - "table_schema": { - "columns": [ - { - "description": "Specify the name of the output field.", - "display_name": "Name", - "filterable": true, - "formatter": "text", - "name": "name", - "sortable": true, - "type": "text" - }, - { - "description": "Describe the purpose of the output field.", - "display_name": "Description", - "filterable": true, - "formatter": "text", - "name": "description", - "sortable": true, - "type": "text" - }, - { - "default": "text", - "description": "Indicate the data type of the output field (e.g., str, int, float, bool, list, dict).", - "display_name": "Type", - "filterable": true, - "formatter": "text", - "name": "type", - "sortable": true, - "type": "text" - }, - { - "default": "False", - "description": "Set to True if this output field should be a list of the specified type.", - "display_name": "Multiple", - "filterable": true, - "formatter": "text", - "name": "multiple", - "sortable": true, - "type": "boolean" - } - ] - }, - "title_case": false, - "trace_as_metadata": true, - "type": "table", - "value": [ - { - "description": "A Positive|Negative value that represents the image.", - "multiple": "False", - "name": "sentiment", - "type": "text" - }, - { - "description": "Brief Description of the image", - "multiple": "False", - "name": "description", - "type": "text" - } - ] - }, - "schema_name": { - "_input_type": "StrInput", - "advanced": false, - "display_name": "Schema Name", - "dynamic": false, - "info": "Provide a name for the output data schema.", - "list": false, - "load_from_db": false, - "name": "schema_name", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "str", - "value": "image_classification" - } - }, - "tool_mode": false - }, - "type": "StructuredOutputComponent" - }, - "dragging": false, - "height": 541, - "id": "StructuredOutputComponent-XYoUc", - "measured": { - "height": 541, - "width": 320 - }, - "position": { - "x": 2029.441019694193, - "y": 414.7974622616549 - }, - "positionAbsolute": { - "x": 2029.441019694193, - "y": 414.7974622616549 - }, - "selected": false, - "type": "genericNode", - "width": 320 - }, - { - "data": { - "id": "ParseData-HzweJ", - "node": { - "base_classes": ["Message"], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert Data into plain text following a specified template.", - "display_name": "Parse Data", - "documentation": "", - "edited": false, - "field_order": ["data", "template", "sep"], - "frozen": false, - "icon": "message-square", - "legacy": false, - "lf_version": "1.0.19.post2", - "metadata": { - "legacy_name": "Parse Data" - }, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Message", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": ["Message"], - "value": "__UNDEFINED__" - }, - { - "allows_loop": false, - "cache": true, - "display_name": "Data List", - "method": "parse_data_as_list", - "name": "data_list", - "selected": "Data", - "tool_mode": true, - "types": ["Data"], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" - }, - "data": { - "_input_type": "DataInput", - "advanced": false, - "display_name": "Data", - "dynamic": false, - "info": "The data to convert to text.", - "input_types": ["Data"], - "list": true, - "name": "data", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "_input_type": "StrInput", - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "", - "list": false, - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "_input_type": "MultilineInput", - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template to use for formatting the data. It can contain the keys {text}, {data} or any other key in the Data.", - "input_types": ["Message"], - "list": false, - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "Sentiment: {sentiment} \n\nDescription: {description} " - } - }, - "tool_mode": false - }, - "type": "ParseData" - }, - "dragging": false, - "height": 302, - "id": "ParseData-HzweJ", - "measured": { - "height": 302, - "width": 320 - }, - "position": { - "x": 2389.490977317181, - "y": 646.9530981549555 - }, - "positionAbsolute": { - "x": 2389.490977317181, - "y": 646.9530981549555 - }, - "selected": false, - "type": "genericNode", - "width": 320 - }, { "data": { "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", - "id": "Prompt-AzK6t", + "id": "Prompt-j1IvC", "node": { - "base_classes": ["Message"], + "base_classes": [ + "Message" + ], "beta": false, "conditional_paths": [], "custom_fields": { @@ -1133,11 +834,13 @@ "display_name": "Prompt", "documentation": "", "edited": false, - "field_order": ["template"], + "field_order": [ + "template" + ], "frozen": false, "icon": "prompts", "legacy": false, - "lf_version": "1.0.19.post2", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -1149,7 +852,9 @@ "name": "prompt", "selected": "Message", "tool_mode": true, - "types": ["Message"], + "types": [ + "Message" + ], "value": "__UNDEFINED__" } ], @@ -1198,7 +903,9 @@ "display_name": "Tool Placeholder", "dynamic": false, "info": "A placeholder input for tool mode.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "load_from_db": false, "name": "tool_placeholder", @@ -1219,7 +926,7 @@ }, "dragging": false, "height": 260, - "id": "Prompt-AzK6t", + "id": "Prompt-j1IvC", "measured": { "height": 260, "width": 320 @@ -1238,9 +945,12 @@ }, { "data": { - "id": "OpenAIModel-cqeNw", + "id": "OpenAIModel-S4vrc", "node": { - "base_classes": ["LanguageModel", "Message"], + "base_classes": [ + "LanguageModel", + "Message" + ], "beta": false, "category": "models", "conditional_paths": [], @@ -1266,6 +976,7 @@ "icon": "OpenAI", "key": "OpenAIModel", "legacy": false, + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -1279,7 +990,9 @@ "required_inputs": [], "selected": "Message", "tool_mode": true, - "types": ["Message"], + "types": [ + "Message" + ], "value": "__UNDEFINED__" }, { @@ -1288,10 +1001,14 @@ "display_name": "Language Model", "method": "build_model", "name": "model_output", - "required_inputs": ["api_key"], + "required_inputs": [ + "api_key" + ], "selected": "LanguageModel", "tool_mode": true, - "types": ["LanguageModel"], + "types": [ + "LanguageModel" + ], "value": "__UNDEFINED__" } ], @@ -1305,7 +1022,9 @@ "display_name": "OpenAI API Key", "dynamic": false, "info": "The OpenAI API Key to use for the OpenAI model.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "load_from_db": true, "name": "api_key", "password": true, @@ -1314,7 +1033,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -1340,7 +1059,9 @@ "display_name": "Input", "dynamic": false, "info": "", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "list_add_label": "Add More", "load_from_db": false, @@ -1522,7 +1243,9 @@ "display_name": "System Message", "dynamic": false, "info": "System message to pass to the model.", - "input_types": ["Message"], + "input_types": [ + "Message" + ], "list": false, "list_add_label": "Add More", "load_from_db": false, @@ -1591,9 +1314,9 @@ "type": "OpenAIModel" }, "dragging": false, - "id": "OpenAIModel-cqeNw", + "id": "OpenAIModel-S4vrc", "measured": { - "height": 653, + "height": 525, "width": 320 }, "position": { @@ -1602,21 +1325,504 @@ }, "selected": false, "type": "genericNode" + }, + { + "data": { + "id": "StructuredOutput-jrD6H", + "node": { + "base_classes": [ + "Data", + "DataFrame" + ], + "beta": false, + "category": "helpers", + "conditional_paths": [], + "custom_fields": {}, + "description": "Transforms LLM responses into **structured data formats**. Ideal for extracting specific information or creating consistent outputs.", + "display_name": "Structured Output", + "documentation": "", + "edited": false, + "field_order": [ + "llm", + "input_value", + "system_prompt", + "schema_name", + "output_schema", + "multiple" + ], + "frozen": false, + "icon": "braces", + "key": "StructuredOutput", + "legacy": false, + "lf_version": "1.2.0", + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Structured Output", + "method": "build_structured_output", + "name": "structured_output", + "selected": "Data", + "tool_mode": true, + "types": [ + "Data" + ], + "value": "__UNDEFINED__" + }, + { + "allows_loop": false, + "cache": true, + "display_name": "DataFrame", + "method": "as_dataframe", + "name": "structured_output_dataframe", + "selected": "DataFrame", + "tool_mode": true, + "types": [ + "DataFrame" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 0.007568328950209746, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "from typing import TYPE_CHECKING, cast\n\nfrom pydantic import BaseModel, Field, create_model\n\nfrom langflow.base.models.chat_result import get_chat_result\nfrom langflow.custom import Component\nfrom langflow.helpers.base_model import build_model_from_schema\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TableInput,\n)\nfrom langflow.schema.data import Data\nfrom langflow.schema.dataframe import DataFrame\nfrom langflow.schema.table import EditMode\n\nif TYPE_CHECKING:\n from langflow.field_typing.constants import LanguageModel\n\n\nclass StructuredOutputComponent(Component):\n display_name = \"Structured Output\"\n description = (\n \"Transforms LLM responses into **structured data formats**. Ideal for extracting specific information \"\n \"or creating consistent outputs.\"\n )\n name = \"StructuredOutput\"\n icon = \"braces\"\n\n inputs = [\n HandleInput(\n name=\"llm\",\n display_name=\"Language Model\",\n info=\"The language model to use to generate the structured output.\",\n input_types=[\"LanguageModel\"],\n required=True,\n ),\n MessageTextInput(\n name=\"input_value\",\n display_name=\"Input Message\",\n info=\"The input message to the language model.\",\n tool_mode=True,\n required=True,\n ),\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Format Instructions\",\n info=\"The instructions to the language model for formatting the output.\",\n value=(\n \"You are an AI system designed to extract structured information from unstructured text.\"\n \"Given the input_text, return a JSON object with predefined keys based on the expected structure.\"\n \"Extract values accurately and format them according to the specified type \"\n \"(e.g., string, integer, float, date).\"\n \"If a value is missing or cannot be determined, return a default \"\n \"(e.g., null, 0, or 'N/A').\"\n \"If multiple instances of the expected structure exist within the input_text, \"\n \"stream each as a separate JSON object.\"\n ),\n required=True,\n advanced=True,\n ),\n MessageTextInput(\n name=\"schema_name\",\n display_name=\"Schema Name\",\n info=\"Provide a name for the output data schema.\",\n advanced=True,\n ),\n TableInput(\n name=\"output_schema\",\n display_name=\"Output Schema\",\n info=\"Define the structure and data types for the model's output.\",\n required=True,\n # TODO: remove deault value\n table_schema=[\n {\n \"name\": \"name\",\n \"display_name\": \"Name\",\n \"type\": \"str\",\n \"description\": \"Specify the name of the output field.\",\n \"default\": \"field\",\n \"edit_mode\": EditMode.INLINE,\n },\n {\n \"name\": \"description\",\n \"display_name\": \"Description\",\n \"type\": \"str\",\n \"description\": \"Describe the purpose of the output field.\",\n \"default\": \"description of field\",\n \"edit_mode\": EditMode.POPOVER,\n },\n {\n \"name\": \"type\",\n \"display_name\": \"Type\",\n \"type\": \"str\",\n \"edit_mode\": EditMode.INLINE,\n \"description\": (\n \"Indicate the data type of the output field (e.g., str, int, float, bool, list, dict).\"\n ),\n \"options\": [\"str\", \"int\", \"float\", \"bool\", \"list\", \"dict\"],\n \"default\": \"str\",\n },\n {\n \"name\": \"multiple\",\n \"display_name\": \"Multiple\",\n \"type\": \"boolean\",\n \"description\": \"Set to True if this output field should be a list of the specified type.\",\n \"default\": \"False\",\n \"edit_mode\": EditMode.INLINE,\n },\n ],\n value=[\n {\n \"name\": \"field\",\n \"description\": \"description of field\",\n \"type\": \"str\",\n \"multiple\": \"False\",\n }\n ],\n ),\n BoolInput(\n name=\"multiple\",\n advanced=True,\n display_name=\"Generate Multiple\",\n info=\"[Deplrecated] Always set to True\",\n value=True,\n ),\n ]\n\n outputs = [\n Output(\n name=\"structured_output\",\n display_name=\"Structured Output\",\n method=\"build_structured_output\",\n ),\n Output(\n name=\"structured_output_dataframe\",\n display_name=\"DataFrame\",\n method=\"as_dataframe\",\n ),\n ]\n\n def build_structured_output_base(self) -> Data:\n schema_name = self.schema_name or \"OutputModel\"\n\n if not hasattr(self.llm, \"with_structured_output\"):\n msg = \"Language model does not support structured output.\"\n raise TypeError(msg)\n if not self.output_schema:\n msg = \"Output schema cannot be empty\"\n raise ValueError(msg)\n\n output_model_ = build_model_from_schema(self.output_schema)\n\n output_model = create_model(\n schema_name,\n objects=(list[output_model_], Field(description=f\"A list of {schema_name}.\")), # type: ignore[valid-type]\n )\n\n try:\n llm_with_structured_output = cast(\"LanguageModel\", self.llm).with_structured_output(schema=output_model) # type: ignore[valid-type, attr-defined]\n\n except NotImplementedError as exc:\n msg = f\"{self.llm.__class__.__name__} does not support structured output.\"\n raise TypeError(msg) from exc\n config_dict = {\n \"run_name\": self.display_name,\n \"project_name\": self.get_project_name(),\n \"callbacks\": self.get_langchain_callbacks(),\n }\n result = get_chat_result(\n runnable=llm_with_structured_output,\n system_message=self.system_prompt,\n input_value=self.input_value,\n config=config_dict,\n )\n if isinstance(result, BaseModel):\n result = result.model_dump()\n if \"objects\" in result:\n return result[\"objects\"]\n return result\n\n def build_structured_output(self) -> Data:\n output = self.build_structured_output_base()\n\n return Data(results=output)\n\n def as_dataframe(self) -> DataFrame:\n output = self.build_structured_output_base()\n if isinstance(output, list):\n return DataFrame(data=output)\n return DataFrame(data=[output])\n" + }, + "input_value": { + "_input_type": "MessageTextInput", + "advanced": false, + "display_name": "Input Message", + "dynamic": false, + "info": "The input message to the language model.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "input_value", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": true, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "" + }, + "llm": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Language Model", + "dynamic": false, + "info": "The language model to use to generate the structured output.", + "input_types": [ + "LanguageModel" + ], + "list": false, + "list_add_label": "Add More", + "name": "llm", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "multiple": { + "_input_type": "BoolInput", + "advanced": true, + "display_name": "Generate Multiple", + "dynamic": false, + "info": "[Deplrecated] Always set to True", + "list": false, + "list_add_label": "Add More", + "name": "multiple", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "bool", + "value": true + }, + "output_schema": { + "_input_type": "TableInput", + "advanced": false, + "display_name": "Output Schema", + "dynamic": false, + "info": "Define the structure and data types for the model's output.", + "is_list": true, + "list_add_label": "Add More", + "name": "output_schema", + "placeholder": "", + "required": true, + "show": true, + "table_icon": "Table", + "table_schema": { + "columns": [ + { + "default": "field", + "description": "Specify the name of the output field.", + "disable_edit": false, + "display_name": "Name", + "edit_mode": "inline", + "filterable": true, + "formatter": "text", + "hidden": false, + "name": "name", + "sortable": true, + "type": "str" + }, + { + "default": "description of field", + "description": "Describe the purpose of the output field.", + "disable_edit": false, + "display_name": "Description", + "edit_mode": "popover", + "filterable": true, + "formatter": "text", + "hidden": false, + "name": "description", + "sortable": true, + "type": "str" + }, + { + "default": "str", + "description": "Indicate the data type of the output field (e.g., str, int, float, bool, list, dict).", + "disable_edit": false, + "display_name": "Type", + "edit_mode": "inline", + "filterable": true, + "formatter": "text", + "hidden": false, + "name": "type", + "options": [ + "str", + "int", + "float", + "bool", + "list", + "dict" + ], + "sortable": true, + "type": "str" + }, + { + "default": false, + "description": "Set to True if this output field should be a list of the specified type.", + "disable_edit": false, + "display_name": "Multiple", + "edit_mode": "inline", + "filterable": true, + "formatter": "boolean", + "hidden": false, + "name": "multiple", + "sortable": true, + "type": "boolean" + } + ] + }, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "trigger_icon": "Table", + "trigger_text": "Open table", + "type": "table", + "value": [ + { + "description": "A Positive|Negative value that represents the image.", + "multiple": "False", + "name": "sentiment", + "type": "str" + }, + { + "description": "Brief Description of the image", + "multiple": false, + "name": "description", + "type": "str" + } + ] + }, + "schema_name": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Schema Name", + "dynamic": false, + "info": "Provide a name for the output data schema.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "schema_name", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "" + }, + "system_prompt": { + "_input_type": "MultilineInput", + "advanced": true, + "copy_field": false, + "display_name": "Format Instructions", + "dynamic": false, + "info": "The instructions to the language model for formatting the output.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "system_prompt", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "You are an AI system designed to extract structured information from unstructured text.Given the input_text, return a JSON object with predefined keys based on the expected structure.Extract values accurately and format them according to the specified type (e.g., string, integer, float, date).If a value is missing or cannot be determined, return a default (e.g., null, 0, or 'N/A').If multiple instances of the expected structure exist within the input_text, stream each as a separate JSON object." + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "StructuredOutput" + }, + "dragging": false, + "id": "StructuredOutput-jrD6H", + "measured": { + "height": 447, + "width": 320 + }, + "position": { + "x": 2029.014435320394, + "y": 390.91002340476973 + }, + "selected": false, + "type": "genericNode" + }, + { + "data": { + "id": "parser-IVklX", + "node": { + "base_classes": [ + "Message" + ], + "beta": false, + "category": "processing", + "conditional_paths": [], + "custom_fields": {}, + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", + "documentation": "", + "edited": false, + "field_order": [ + "mode", + "pattern", + "input_data", + "sep" + ], + "frozen": false, + "icon": "braces", + "key": "parser", + "legacy": false, + "lf_version": "1.2.0", + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", + "selected": "Message", + "tool_mode": true, + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 2.220446049250313e-16, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n name = \"parser\"\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" + }, + "input_data": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Data or DataFrame", + "dynamic": false, + "info": "Accepts either a DataFrame or a Data object.", + "input_types": [ + "DataFrame", + "Data" + ], + "list": false, + "list_add_label": "Add More", + "name": "input_data", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Parser" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "Sentiment: {sentiment} Description: {description} " + }, + "sep": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Separator", + "dynamic": false, + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "sep", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "\n" + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "parser" + }, + "dragging": false, + "id": "parser-IVklX", + "measured": { + "height": 395, + "width": 320 + }, + "position": { + "x": 2381.0436064002697, + "y": 353.98212620918343 + }, + "selected": true, + "type": "genericNode" } ], "viewport": { - "x": -426.91879919031885, - "y": 21.85679755101154, - "zoom": 0.6313688898572775 + "x": -282.47108266384464, + "y": 179.13713712012208, + "zoom": 0.5222378453386497 } }, "description": "Analyzes images and categorizes them as positive, negative, or neutral using zero-shot learning.", "endpoint_name": null, - "gradient": "2", - "icon": "Image", - "id": "0caf0da8-c233-4fc5-9df3-41bb58403885", + "id": "210ef2ad-2a88-4fe2-be1f-6ac73b226b42", "is_component": false, - "last_tested_version": "1.0.19.post2", + "last_tested_version": "1.2.0", "name": "Image Sentiment Analysis", - "tags": ["classification"] -} + "tags": [ + "classification" + ] +} \ No newline at end of file diff --git a/src/backend/base/langflow/initial_setup/starter_projects/LoopTemplate.json b/src/backend/base/langflow/initial_setup/starter_projects/LoopTemplate.json index 6f5266399..e27519e0c 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/LoopTemplate.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/LoopTemplate.json @@ -1,69 +1,13 @@ { "data": { "edges": [ - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "LoopComponent", - "id": "LoopComponent-Ayr6F", - "name": "item", - "output_types": [ - "Data" - ] - }, - "targetHandle": { - "fieldName": "data", - "id": "ParseData-4kg7C", - "inputTypes": [ - "Data" - ], - "type": "other" - } - }, - "id": "reactflow__edge-LoopComponent-Ayr6F{œdataTypeœ:œLoopComponentœ,œidœ:œLoopComponent-Ayr6Fœ,œnameœ:œitemœ,œoutput_typesœ:[œDataœ]}-ParseData-4kg7C{œfieldNameœ:œdataœ,œidœ:œParseData-4kg7Cœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", - "selected": false, - "source": "LoopComponent-Ayr6F", - "sourceHandle": "{œdataTypeœ: œLoopComponentœ, œidœ: œLoopComponent-Ayr6Fœ, œnameœ: œitemœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-4kg7C", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-4kg7Cœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-4kg7C", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "AnthropicModel-EIKEJ", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-4kg7C{œdataTypeœ:œParseDataœ,œidœ:œParseData-4kg7Cœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-AnthropicModel-EIKEJ{œfieldNameœ:œinput_valueœ,œidœ:œAnthropicModel-EIKEJœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-4kg7C", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-4kg7Cœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "AnthropicModel-EIKEJ", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAnthropicModel-EIKEJœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "AnthropicModel", - "id": "AnthropicModel-EIKEJ", + "id": "AnthropicModel-VobAp", "name": "text_output", "output_types": [ "Message" @@ -71,19 +15,19 @@ }, "targetHandle": { "fieldName": "message", - "id": "MessagetoData-XJar4", + "id": "MessagetoData-8vLbf", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-AnthropicModel-EIKEJ{œdataTypeœ:œAnthropicModelœ,œidœ:œAnthropicModel-EIKEJœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-MessagetoData-XJar4{œfieldNameœ:œmessageœ,œidœ:œMessagetoData-XJar4œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-AnthropicModel-VobAp{œdataTypeœ:œAnthropicModelœ,œidœ:œAnthropicModel-VobApœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-MessagetoData-8vLbf{œfieldNameœ:œmessageœ,œidœ:œMessagetoData-8vLbfœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "AnthropicModel-EIKEJ", - "sourceHandle": "{œdataTypeœ: œAnthropicModelœ, œidœ: œAnthropicModel-EIKEJœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "MessagetoData-XJar4", - "targetHandle": "{œfieldNameœ: œmessageœ, œidœ: œMessagetoData-XJar4œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "AnthropicModel-VobAp", + "sourceHandle": "{œdataTypeœ: œAnthropicModelœ, œidœ: œAnthropicModel-VobApœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "MessagetoData-8vLbf", + "targetHandle": "{œfieldNameœ: œmessageœ, œidœ: œMessagetoData-8vLbfœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -91,7 +35,7 @@ "data": { "sourceHandle": { "dataType": "MessagetoData", - "id": "MessagetoData-XJar4", + "id": "MessagetoData-8vLbf", "name": "data", "output_types": [ "Data" @@ -99,19 +43,19 @@ }, "targetHandle": { "dataType": "LoopComponent", - "id": "LoopComponent-Ayr6F", + "id": "LoopComponent-0aBsp", "name": "item", "output_types": [ "Data" ] } }, - "id": "reactflow__edge-MessagetoData-XJar4{œdataTypeœ:œMessagetoDataœ,œidœ:œMessagetoData-XJar4œ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-LoopComponent-Ayr6F{œdataTypeœ:œLoopComponentœ,œidœ:œLoopComponent-Ayr6Fœ,œnameœ:œitemœ,œoutput_typesœ:[œDataœ]}", + "id": "reactflow__edge-MessagetoData-8vLbf{œdataTypeœ:œMessagetoDataœ,œidœ:œMessagetoData-8vLbfœ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-LoopComponent-0aBsp{œdataTypeœ:œLoopComponentœ,œidœ:œLoopComponent-0aBspœ,œnameœ:œitemœ,œoutput_typesœ:[œDataœ]}", "selected": false, - "source": "MessagetoData-XJar4", - "sourceHandle": "{œdataTypeœ: œMessagetoDataœ, œidœ: œMessagetoData-XJar4œ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", - "target": "LoopComponent-Ayr6F", - "targetHandle": "{œdataTypeœ: œLoopComponentœ, œidœ: œLoopComponent-Ayr6Fœ, œnameœ: œitemœ, œoutput_typesœ: [œDataœ]}" + "source": "MessagetoData-8vLbf", + "sourceHandle": "{œdataTypeœ: œMessagetoDataœ, œidœ: œMessagetoData-8vLbfœ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", + "target": "LoopComponent-0aBsp", + "targetHandle": "{œdataTypeœ: œLoopComponentœ, œidœ: œLoopComponent-0aBspœ, œnameœ: œitemœ, œoutput_typesœ: [œDataœ]}" }, { "animated": false, @@ -119,7 +63,7 @@ "data": { "sourceHandle": { "dataType": "LoopComponent", - "id": "LoopComponent-Ayr6F", + "id": "LoopComponent-0aBsp", "name": "done", "output_types": [ "Data" @@ -127,19 +71,19 @@ }, "targetHandle": { "fieldName": "data", - "id": "ParseData-jfscS", + "id": "ParseData-J2Axc", "inputTypes": [ "Data" ], "type": "other" } }, - "id": "reactflow__edge-LoopComponent-Ayr6F{œdataTypeœ:œLoopComponentœ,œidœ:œLoopComponent-Ayr6Fœ,œnameœ:œdoneœ,œoutput_typesœ:[œDataœ]}-ParseData-jfscS{œfieldNameœ:œdataœ,œidœ:œParseData-jfscSœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-LoopComponent-0aBsp{œdataTypeœ:œLoopComponentœ,œidœ:œLoopComponent-0aBspœ,œnameœ:œdoneœ,œoutput_typesœ:[œDataœ]}-ParseData-J2Axc{œfieldNameœ:œdataœ,œidœ:œParseData-J2Axcœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", "selected": false, - "source": "LoopComponent-Ayr6F", - "sourceHandle": "{œdataTypeœ: œLoopComponentœ, œidœ: œLoopComponent-Ayr6Fœ, œnameœ: œdoneœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-jfscS", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-jfscSœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" + "source": "LoopComponent-0aBsp", + "sourceHandle": "{œdataTypeœ: œLoopComponentœ, œidœ: œLoopComponent-0aBspœ, œnameœ: œdoneœ, œoutput_typesœ: [œDataœ]}", + "target": "ParseData-J2Axc", + "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-J2Axcœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -147,7 +91,7 @@ "data": { "sourceHandle": { "dataType": "ParseData", - "id": "ParseData-jfscS", + "id": "ParseData-J2Axc", "name": "text", "output_types": [ "Message" @@ -155,7 +99,7 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-B66b2", + "id": "ChatOutput-01dLy", "inputTypes": [ "Data", "DataFrame", @@ -164,12 +108,12 @@ "type": "str" } }, - "id": "reactflow__edge-ParseData-jfscS{œdataTypeœ:œParseDataœ,œidœ:œParseData-jfscSœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-B66b2{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-B66b2œ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ParseData-J2Axc{œdataTypeœ:œParseDataœ,œidœ:œParseData-J2Axcœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-01dLy{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-01dLyœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "ParseData-jfscS", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-jfscSœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-B66b2", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-B66b2œ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" + "source": "ParseData-J2Axc", + "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-J2Axcœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-01dLy", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-01dLyœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -177,7 +121,7 @@ "data": { "sourceHandle": { "dataType": "ChatInput", - "id": "ChatInput-2VCkW", + "id": "ChatInput-HBlBP", "name": "message", "output_types": [ "Message" @@ -185,27 +129,26 @@ }, "targetHandle": { "fieldName": "search_query", - "id": "ArXivComponent-qDXvl", + "id": "ArXivComponent-sSqo4", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-ChatInput-2VCkW{œdataTypeœ:œChatInputœ,œidœ:œChatInput-2VCkWœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-ArXivComponent-qDXvl{œfieldNameœ:œsearch_queryœ,œidœ:œArXivComponent-qDXvlœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-HBlBP{œdataTypeœ:œChatInputœ,œidœ:œChatInput-HBlBPœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-ArXivComponent-sSqo4{œfieldNameœ:œsearch_queryœ,œidœ:œArXivComponent-sSqo4œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "ChatInput-2VCkW", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-2VCkWœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "ArXivComponent-qDXvl", - "targetHandle": "{œfieldNameœ: œsearch_queryœ, œidœ: œArXivComponent-qDXvlœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "ChatInput-HBlBP", + "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-HBlBPœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "ArXivComponent-sSqo4", + "targetHandle": "{œfieldNameœ: œsearch_queryœ, œidœ: œArXivComponent-sSqo4œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, - "className": "", "data": { "sourceHandle": { "dataType": "ArXivComponent", - "id": "ArXivComponent-qDXvl", + "id": "ArXivComponent-sSqo4", "name": "data", "output_types": [ "Data" @@ -213,25 +156,80 @@ }, "targetHandle": { "fieldName": "data", - "id": "LoopComponent-Ayr6F", + "id": "LoopComponent-0aBsp", "inputTypes": [ "Data" ], "type": "other" } }, - "id": "reactflow__edge-ArXivComponent-qDXvl{œdataTypeœ:œArXivComponentœ,œidœ:œArXivComponent-qDXvlœ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-LoopComponent-Ayr6F{œfieldNameœ:œdataœ,œidœ:œLoopComponent-Ayr6Fœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", + "id": "xy-edge__ArXivComponent-sSqo4{œdataTypeœ:œArXivComponentœ,œidœ:œArXivComponent-sSqo4œ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-LoopComponent-0aBsp{œfieldNameœ:œdataœ,œidœ:œLoopComponent-0aBspœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", "selected": false, - "source": "ArXivComponent-qDXvl", - "sourceHandle": "{œdataTypeœ: œArXivComponentœ, œidœ: œArXivComponent-qDXvlœ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", - "target": "LoopComponent-Ayr6F", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œLoopComponent-Ayr6Fœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" + "source": "ArXivComponent-sSqo4", + "sourceHandle": "{œdataTypeœ: œArXivComponentœ, œidœ: œArXivComponent-sSqo4œ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", + "target": "LoopComponent-0aBsp", + "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œLoopComponent-0aBspœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-lOwhH", + "name": "parsed_text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "AnthropicModel-VobAp", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "xy-edge__parser-lOwhH{œdataTypeœ:œparserœ,œidœ:œparser-lOwhHœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-AnthropicModel-VobAp{œfieldNameœ:œinput_valueœ,œidœ:œAnthropicModel-VobApœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "parser-lOwhH", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-lOwhHœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "AnthropicModel-VobAp", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAnthropicModel-VobApœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + }, + { + "animated": false, + "data": { + "sourceHandle": { + "dataType": "LoopComponent", + "id": "LoopComponent-0aBsp", + "name": "item", + "output_types": [ + "Data" + ] + }, + "targetHandle": { + "fieldName": "input_data", + "id": "parser-lOwhH", + "inputTypes": [ + "DataFrame", + "Data" + ], + "type": "other" + } + }, + "id": "xy-edge__LoopComponent-0aBsp{œdataTypeœ:œLoopComponentœ,œidœ:œLoopComponent-0aBspœ,œnameœ:œitemœ,œoutput_typesœ:[œDataœ]}-parser-lOwhH{œfieldNameœ:œinput_dataœ,œidœ:œparser-lOwhHœ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", + "selected": false, + "source": "LoopComponent-0aBsp", + "sourceHandle": "{œdataTypeœ: œLoopComponentœ, œidœ: œLoopComponent-0aBspœ, œnameœ: œitemœ, œoutput_typesœ: [œDataœ]}", + "target": "parser-lOwhH", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-lOwhHœ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" } ], "nodes": [ { "data": { - "id": "ArXivComponent-qDXvl", + "id": "ArXivComponent-sSqo4", "node": { "base_classes": [ "Data" @@ -378,7 +376,7 @@ "type": "ArXivComponent" }, "dragging": false, - "id": "ArXivComponent-qDXvl", + "id": "ArXivComponent-sSqo4", "measured": { "height": 443, "width": 320 @@ -392,7 +390,7 @@ }, { "data": { - "id": "LoopComponent-Ayr6F", + "id": "LoopComponent-0aBsp", "node": { "base_classes": [ "Data" @@ -495,7 +493,7 @@ "type": "LoopComponent" }, "dragging": false, - "id": "LoopComponent-Ayr6F", + "id": "LoopComponent-0aBsp", "measured": { "height": 280, "width": 320 @@ -509,172 +507,7 @@ }, { "data": { - "id": "ParseData-4kg7C", - "node": { - "base_classes": [ - "Data", - "Message" - ], - "beta": false, - "category": "processing", - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert Data objects into Messages using any {field_name} from input data.", - "display_name": "Data to Message", - "documentation": "", - "edited": false, - "field_order": [ - "data", - "template", - "sep" - ], - "frozen": false, - "icon": "message-square", - "key": "ParseData", - "legacy": false, - "lf_version": "1.1.5", - "metadata": { - "legacy_name": "Parse Data" - }, - "minimized": false, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Message", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - }, - { - "allows_loop": false, - "cache": true, - "display_name": "Data List", - "method": "parse_data_as_list", - "name": "data_list", - "selected": "Data", - "tool_mode": true, - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "score": 0.01857804455091699, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" - }, - "data": { - "_input_type": "DataInput", - "advanced": false, - "display_name": "Data", - "dynamic": false, - "info": "The data to convert to text.", - "input_types": [ - "Data" - ], - "list": true, - "list_add_label": "Add More", - "name": "data", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "_input_type": "StrInput", - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "", - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "_input_type": "MultilineInput", - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template to use for formatting the data. It can contain the keys {text}, {data} or any other key in the Data.", - "input_types": [ - "Message" - ], - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "{data}" - } - }, - "tool_mode": false - }, - "showNode": true, - "type": "ParseData" - }, - "dragging": false, - "id": "ParseData-4kg7C", - "measured": { - "height": 342, - "width": 320 - }, - "position": { - "x": 996.5733307455723, - "y": 35.284413822605146 - }, - "selected": false, - "type": "genericNode" - }, - { - "data": { - "id": "AnthropicModel-EIKEJ", + "id": "AnthropicModel-VobAp", "node": { "base_classes": [ "LanguageModel", @@ -762,7 +595,7 @@ "show": true, "title_case": false, "type": "str", - "value": "ANTHROPIC_API_KEY" + "value": "" }, "base_url": { "_input_type": "MessageTextInput", @@ -996,7 +829,7 @@ "type": "AnthropicModel" }, "dragging": false, - "id": "AnthropicModel-EIKEJ", + "id": "AnthropicModel-VobAp", "measured": { "height": 670, "width": 320 @@ -1010,7 +843,7 @@ }, { "data": { - "id": "MessagetoData-XJar4", + "id": "MessagetoData-8vLbf", "node": { "base_classes": [ "Data" @@ -1101,7 +934,7 @@ "type": "MessagetoData" }, "dragging": false, - "id": "MessagetoData-XJar4", + "id": "MessagetoData-8vLbf", "measured": { "height": 230, "width": 320 @@ -1115,7 +948,7 @@ }, { "data": { - "id": "ParseData-jfscS", + "id": "ParseData-J2Axc", "node": { "base_classes": [ "Data", @@ -1137,7 +970,7 @@ "frozen": false, "icon": "message-square", "key": "ParseData", - "legacy": false, + "legacy": true, "lf_version": "1.1.5", "metadata": { "legacy_name": "Parse Data" @@ -1192,7 +1025,7 @@ "show": true, "title_case": false, "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" + "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n legacy = True\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" }, "data": { "_input_type": "DataInput", @@ -1266,7 +1099,7 @@ "type": "ParseData" }, "dragging": false, - "id": "ParseData-jfscS", + "id": "ParseData-J2Axc", "measured": { "height": 342, "width": 320 @@ -1280,7 +1113,7 @@ }, { "data": { - "id": "ChatOutput-B66b2", + "id": "ChatOutput-01dLy", "node": { "base_classes": [ "Message" @@ -1575,7 +1408,7 @@ "type": "ChatOutput" }, "dragging": false, - "id": "ChatOutput-B66b2", + "id": "ChatOutput-01dLy", "measured": { "height": 66, "width": 192 @@ -1589,7 +1422,7 @@ }, { "data": { - "id": "ChatInput-2VCkW", + "id": "ChatInput-HBlBP", "node": { "base_classes": [ "Message" @@ -1739,7 +1572,6 @@ "placeholder": "", "required": false, "show": true, - "temp_file": true, "title_case": false, "trace_as_metadata": true, "type": "file", @@ -1884,7 +1716,7 @@ "type": "ChatInput" }, "dragging": false, - "id": "ChatInput-2VCkW", + "id": "ChatInput-HBlBP", "measured": { "height": 66, "width": 192 @@ -1898,7 +1730,7 @@ }, { "data": { - "id": "note-yeBjr", + "id": "note-EXWDb", "node": { "description": "### 💡 Add your Anthropic API key here 👇", "display_name": "", @@ -1911,7 +1743,7 @@ }, "dragging": false, "height": 324, - "id": "note-yeBjr", + "id": "note-EXWDb", "measured": { "height": 324, "width": 358 @@ -1927,9 +1759,9 @@ }, { "data": { - "id": "note-Mkx31", + "id": "note-chYLV", "node": { - "description": "# **Langflow Loop Component Template - ArXiv search result Translator** \nThis template translates research paper summaries on ArXiv into Portuguese and summarizes them. \n Using **Langflow’s looping mechanism**, the template iterates through multiple research papers, translates them with the **Anthropic** model component, and outputs an aggregated version of all translated papers. \n\n## Quickstart \n 1. Add your Anthropic API key to the **Anthropic** component. \n2. In the **Playground**, enter a query related to a research topic (for example, “Quantum Computing Advancements”). \n\n The flow fetches a list of research papers from ArXiv matching the query. Each paper in the retrieved list is processed one-by-one using the Langflow **Loop component**. \n\n The abstract of each paper is translated into Portuguese by the **Anthropic** model component. \n\n Once all papers are translated, the system aggregates them into a **single structured output**.", + "description": "# **Langflow Loop Component Template - ArXiv search result Translator** \nThis template translates research paper summaries on ArXiv into Portuguese and summarizes them. \n Using **Langflow’s looping mechanism**, the template iterates through multiple research papers, translates them with the **Anthropic** model component, and outputs an aggregated version of all translated papers. \n\n# # Quickstart \n 1. Add your Anthropic API key to the **Anthropic** component. \n2. In the **Playground**, enter a query related to a research topic (for example, “Quantum Computing Advancements”). \n\n The flow fetches a list of research papers from ArXiv matching the query. Each paper in the retrieved list is processed one-by-one using the Langflow **Loop component**. \n\n The abstract of each paper is translated into Portuguese by the **Anthropic** model component. \n\n Once all papers are translated, the system aggregates them into a **single structured output**.", "display_name": "", "documentation": "", "template": {} @@ -1938,7 +1770,7 @@ }, "dragging": false, "height": 647, - "id": "note-Mkx31", + "id": "note-chYLV", "measured": { "height": 647, "width": 577 @@ -1951,17 +1783,191 @@ "selected": false, "type": "noteNode", "width": 576 + }, + { + "data": { + "id": "parser-lOwhH", + "node": { + "base_classes": [ + "Message" + ], + "beta": false, + "category": "processing", + "conditional_paths": [], + "custom_fields": {}, + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", + "documentation": "", + "edited": false, + "field_order": [ + "mode", + "pattern", + "input_data", + "sep" + ], + "frozen": false, + "icon": "braces", + "key": "parser", + "legacy": false, + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", + "selected": "Message", + "tool_mode": true, + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 2.220446049250313e-16, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n name = \"parser\"\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" + }, + "input_data": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Data or DataFrame", + "dynamic": false, + "info": "Accepts either a DataFrame or a Data object.", + "input_types": [ + "DataFrame", + "Data" + ], + "list": false, + "list_add_label": "Add More", + "name": "input_data", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Stringify" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": false, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "Text: {text}" + }, + "sep": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Separator", + "dynamic": false, + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "sep", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "\n" + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "parser" + }, + "dragging": false, + "id": "parser-lOwhH", + "measured": { + "height": 312, + "width": 320 + }, + "position": { + "x": 961.4680671279477, + "y": -109.99346873464856 + }, + "selected": true, + "type": "genericNode" } ], "viewport": { - "x": 437.2271770749776, - "y": 389.23678827947083, - "zoom": 0.42811620344860135 + "x": 235.58653718700498, + "y": 250.7016431547001, + "zoom": 0.4882257444235303 } }, "description": "This template iterates over search results using LoopComponent and translates each result into Portuguese automatically. 🚀", "endpoint_name": null, - "id": "aa7539cb-9c2e-4d25-b5df-c107a60591a1", + "id": "16326186-363a-46b4-aba2-08f76e31e38c", "is_component": false, "last_tested_version": "1.2.0", "name": "Research Translation Loop", 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 1c48aed16..27b3ba167 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,41 +1,13 @@ { "data": { "edges": [ - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "StructuredOutputComponent", - "id": "StructuredOutputComponent-HNJw1", - "name": "structured_output", - "output_types": [ - "Data" - ] - }, - "targetHandle": { - "fieldName": "data", - "id": "ParseData-7nw3f", - "inputTypes": [ - "Data" - ], - "type": "other" - } - }, - "id": "reactflow__edge-StructuredOutputComponent-HNJw1{œdataTypeœ:œStructuredOutputComponentœ,œidœ:œStructuredOutputComponent-HNJw1œ,œnameœ:œstructured_outputœ,œoutput_typesœ:[œDataœ]}-ParseData-7nw3f{œfieldNameœ:œdataœ,œidœ:œParseData-7nw3fœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", - "selected": false, - "source": "StructuredOutputComponent-HNJw1", - "sourceHandle": "{œdataTypeœ: œStructuredOutputComponentœ, œidœ: œStructuredOutputComponent-HNJw1œ, œnameœ: œstructured_outputœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-7nw3f", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-7nw3fœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" - }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "ChatInput", - "id": "ChatInput-hLHl2", + "id": "ChatInput-b4sJc", "name": "message", "output_types": [ "Message" @@ -43,19 +15,19 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "Agent-ZlvTd", + "id": "Agent-bjWdX", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-ChatInput-hLHl2{œdataTypeœ:œChatInputœ,œidœ:œChatInput-hLHl2œ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Agent-ZlvTd{œfieldNameœ:œinput_valueœ,œidœ:œAgent-ZlvTdœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-b4sJc{œdataTypeœ:œChatInputœ,œidœ:œChatInput-b4sJcœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Agent-bjWdX{œfieldNameœ:œinput_valueœ,œidœ:œAgent-bjWdXœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "ChatInput-hLHl2", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-hLHl2œ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "Agent-ZlvTd", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAgent-ZlvTdœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "ChatInput-b4sJc", + "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-b4sJcœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "Agent-bjWdX", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAgent-bjWdXœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -63,7 +35,7 @@ "data": { "sourceHandle": { "dataType": "Agent", - "id": "Agent-ZlvTd", + "id": "Agent-bjWdX", "name": "response", "output_types": [ "Message" @@ -71,19 +43,19 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "StructuredOutputComponent-HNJw1", + "id": "StructuredOutput-5OFKk", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-Agent-ZlvTd{œdataTypeœ:œAgentœ,œidœ:œAgent-ZlvTdœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-StructuredOutputComponent-HNJw1{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutputComponent-HNJw1œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Agent-bjWdX{œdataTypeœ:œAgentœ,œidœ:œAgent-bjWdXœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-StructuredOutput-5OFKk{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutput-5OFKkœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Agent-ZlvTd", - "sourceHandle": "{œdataTypeœ: œAgentœ, œidœ: œAgent-ZlvTdœ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}", - "target": "StructuredOutputComponent-HNJw1", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œStructuredOutputComponent-HNJw1œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "Agent-bjWdX", + "sourceHandle": "{œdataTypeœ: œAgentœ, œidœ: œAgent-bjWdXœ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}", + "target": "StructuredOutput-5OFKk", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œStructuredOutput-5OFKkœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -91,7 +63,7 @@ "data": { "sourceHandle": { "dataType": "TavilySearchComponent", - "id": "TavilySearchComponent-Fl2MN", + "id": "TavilySearchComponent-vpPJd", "name": "component_as_tool", "output_types": [ "Tool" @@ -99,19 +71,19 @@ }, "targetHandle": { "fieldName": "tools", - "id": "Agent-ZlvTd", + "id": "Agent-bjWdX", "inputTypes": [ "Tool" ], "type": "other" } }, - "id": "reactflow__edge-TavilySearchComponent-Fl2MN{œdataTypeœ:œTavilySearchComponentœ,œidœ:œTavilySearchComponent-Fl2MNœ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}-Agent-ZlvTd{œfieldNameœ:œtoolsœ,œidœ:œAgent-ZlvTdœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-TavilySearchComponent-vpPJd{œdataTypeœ:œTavilySearchComponentœ,œidœ:œTavilySearchComponent-vpPJdœ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}-Agent-bjWdX{œfieldNameœ:œtoolsœ,œidœ:œAgent-bjWdXœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "selected": false, - "source": "TavilySearchComponent-Fl2MN", - "sourceHandle": "{œdataTypeœ: œTavilySearchComponentœ, œidœ: œTavilySearchComponent-Fl2MNœ, œnameœ: œcomponent_as_toolœ, œoutput_typesœ: [œToolœ]}", - "target": "Agent-ZlvTd", - "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œAgent-ZlvTdœ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}" + "source": "TavilySearchComponent-vpPJd", + "sourceHandle": "{œdataTypeœ: œTavilySearchComponentœ, œidœ: œTavilySearchComponent-vpPJdœ, œnameœ: œcomponent_as_toolœ, œoutput_typesœ: [œToolœ]}", + "target": "Agent-bjWdX", + "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œAgent-bjWdXœ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -119,7 +91,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-GOv57", + "id": "OpenAIModel-2q7JZ", "name": "model_output", "output_types": [ "LanguageModel" @@ -127,35 +99,61 @@ }, "targetHandle": { "fieldName": "llm", - "id": "StructuredOutputComponent-HNJw1", + "id": "StructuredOutput-5OFKk", "inputTypes": [ "LanguageModel" ], "type": "other" } }, - "id": "reactflow__edge-OpenAIModel-GOv57{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-GOv57œ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutputComponent-HNJw1{œfieldNameœ:œllmœ,œidœ:œStructuredOutputComponent-HNJw1œ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-OpenAIModel-2q7JZ{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-2q7JZœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutput-5OFKk{œfieldNameœ:œllmœ,œidœ:œStructuredOutput-5OFKkœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", "selected": false, - "source": "OpenAIModel-GOv57", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-GOv57œ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", - "target": "StructuredOutputComponent-HNJw1", - "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œStructuredOutputComponent-HNJw1œ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" + "source": "OpenAIModel-2q7JZ", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-2q7JZœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", + "target": "StructuredOutput-5OFKk", + "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œStructuredOutput-5OFKkœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" }, { "animated": false, - "className": "", "data": { "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-7nw3f", - "name": "text", + "dataType": "StructuredOutput", + "id": "StructuredOutput-5OFKk", + "name": "structured_output_dataframe", + "output_types": [ + "DataFrame" + ] + }, + "targetHandle": { + "fieldName": "input_data", + "id": "parser-7JQpB", + "inputTypes": [ + "DataFrame", + "Data" + ], + "type": "other" + } + }, + "id": "xy-edge__StructuredOutput-5OFKk{œdataTypeœ:œStructuredOutputœ,œidœ:œStructuredOutput-5OFKkœ,œnameœ:œstructured_output_dataframeœ,œoutput_typesœ:[œDataFrameœ]}-parser-7JQpB{œfieldNameœ:œinput_dataœ,œidœ:œparser-7JQpBœ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", + "selected": false, + "source": "StructuredOutput-5OFKk", + "sourceHandle": "{œdataTypeœ: œStructuredOutputœ, œidœ: œStructuredOutput-5OFKkœ, œnameœ: œstructured_output_dataframeœ, œoutput_typesœ: [œDataFrameœ]}", + "target": "parser-7JQpB", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-7JQpBœ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" + }, + { + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-7JQpB", + "name": "parsed_text", "output_types": [ "Message" ] }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-F8JI7", + "id": "ChatOutput-CFSA4", "inputTypes": [ "Data", "DataFrame", @@ -164,12 +162,11 @@ "type": "str" } }, - "id": "reactflow__edge-ParseData-7nw3f{œdataTypeœ:œParseDataœ,œidœ:œParseData-7nw3fœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-F8JI7{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-F8JI7œ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-7nw3f", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-7nw3fœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-F8JI7", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-F8JI7œ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" + "id": "xy-edge__parser-7JQpB{œdataTypeœ:œparserœ,œidœ:œparser-7JQpBœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-CFSA4{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-CFSA4œ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "source": "parser-7JQpB", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-7JQpBœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-CFSA4", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-CFSA4œ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" } ], "nodes": [ @@ -177,7 +174,7 @@ "data": { "description": "Get chat inputs from the Playground.", "display_name": "Chat Input", - "id": "ChatInput-hLHl2", + "id": "ChatInput-b4sJc", "node": { "base_classes": [ "Message" @@ -203,7 +200,7 @@ "frozen": false, "icon": "MessagesSquare", "legacy": false, - "lf_version": "1.1.1", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -452,7 +449,7 @@ }, "dragging": false, "height": 234, - "id": "ChatInput-hLHl2", + "id": "ChatInput-b4sJc", "measured": { "height": 234, "width": 320 @@ -473,7 +470,7 @@ "data": { "description": "Display a chat message in the Playground.", "display_name": "Chat Output", - "id": "ChatOutput-F8JI7", + "id": "ChatOutput-CFSA4", "node": { "base_classes": [ "Message" @@ -499,7 +496,7 @@ "frozen": false, "icon": "MessagesSquare", "legacy": false, - "lf_version": "1.1.1", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -755,7 +752,7 @@ }, "dragging": false, "height": 234, - "id": "ChatOutput-F8JI7", + "id": "ChatOutput-CFSA4", "measured": { "height": 234, "width": 320 @@ -774,83 +771,9 @@ }, { "data": { - "id": "note-EQ8do", + "id": "note-UqfqM", "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": "", - "documentation": "", - "template": { - "backgroundColor": "blue" - } - }, - "type": "note" - }, - "dragging": false, - "height": 324, - "id": "note-EQ8do", - "measured": { - "height": 324, - "width": 325 - }, - "position": { - "x": 2130.958950603199, - "y": 421.74182837210094 - }, - "positionAbsolute": { - "x": 2089.5869930853464, - "y": 311.41660832449514 - }, - "resizing": false, - "selected": false, - "style": { - "height": 324, - "width": 324 - }, - "type": "noteNode", - "width": 324 - }, - { - "data": { - "id": "note-4z8Ww", - "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": "", - "documentation": "", - "template": { - "backgroundColor": "blue" - } - }, - "type": "note" - }, - "dragging": false, - "height": 324, - "id": "note-4z8Ww", - "measured": { - "height": 324, - "width": 325 - }, - "position": { - "x": 1284.9450195065508, - "y": 158.82084648405578 - }, - "positionAbsolute": { - "x": 1237.6627823432912, - "y": 169.53860932079613 - }, - "resizing": false, - "selected": false, - "style": { - "height": 324, - "width": 324 - }, - "type": "noteNode", - "width": 324 - }, - { - "data": { - "id": "note-NTyrO", - "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! 🔍💼", + "description": "# Market Research\nThis flow helps you gather comprehensive information about companies for sales and business intelligence purposes.\n\n## Prerequisites\n\n- **[Tavily API Key](https://docs.tavily.com/welcome)**\n- **[OpenAI API Key](https://platform.openai.com/)**\n\n## Quickstart\n\n1. Add your **OpenAI API key** to the **OpenAI** model and **Agent** components.\n2. Add your **Tavily API key** to the **Tavily Search** component.\n3. In the **Chat Input**, enter a company name you want to research.\n4. Open the **Playground** and research the company. The **Structured Output** component transforms the raw LLM response into structured data, and the **Parser** component presents the data as text for the **Chat output** component to present.", "display_name": "", "documentation": "", "template": { @@ -860,15 +783,15 @@ "type": "note" }, "dragging": false, - "height": 324, - "id": "note-NTyrO", + "height": 671, + "id": "note-UqfqM", "measured": { - "height": 324, - "width": 325 + "height": 671, + "width": 660 }, "position": { - "x": 465.57341046298257, - "y": 459.2036503168611 + "x": -226.74339309333172, + "y": 683.3969749619654 }, "positionAbsolute": { "x": 244.92297036777086, @@ -881,16 +804,17 @@ "width": 324 }, "type": "noteNode", - "width": 324 + "width": 659 }, { "data": { "description": "Transforms LLM responses into **structured data formats**. Ideal for extracting specific information or creating consistent outputs.", "display_name": "Structured Output", - "id": "StructuredOutputComponent-HNJw1", + "id": "StructuredOutput-5OFKk", "node": { "base_classes": [ - "Data" + "Data", + "DataFrame" ], "beta": false, "conditional_paths": [], @@ -902,6 +826,7 @@ "field_order": [ "llm", "input_value", + "system_prompt", "schema_name", "output_schema", "multiple" @@ -909,20 +834,36 @@ "frozen": false, "icon": "braces", "legacy": false, - "lf_version": "1.1.1", + "lf_version": "1.2.0", "metadata": {}, + "minimized": false, "output_types": [], "outputs": [ { + "allows_loop": false, "cache": true, "display_name": "Structured Output", "method": "build_structured_output", "name": "structured_output", "selected": "Data", + "tool_mode": true, "types": [ "Data" ], "value": "__UNDEFINED__" + }, + { + "allows_loop": false, + "cache": true, + "display_name": "DataFrame", + "method": "as_dataframe", + "name": "structured_output_dataframe", + "selected": "DataFrame", + "tool_mode": true, + "types": [ + "DataFrame" + ], + "value": "__UNDEFINED__" } ], "pinned": false, @@ -944,25 +885,26 @@ "show": true, "title_case": false, "type": "code", - "value": "from typing import TYPE_CHECKING, cast\n\nfrom pydantic import BaseModel, Field, create_model\n\nfrom langflow.base.models.chat_result import get_chat_result\nfrom langflow.custom import Component\nfrom langflow.helpers.base_model import build_model_from_schema\nfrom langflow.io import BoolInput, HandleInput, MessageTextInput, Output, StrInput, TableInput\nfrom langflow.schema.data import Data\n\nif TYPE_CHECKING:\n from langflow.field_typing.constants import LanguageModel\n\n\nclass StructuredOutputComponent(Component):\n display_name = \"Structured Output\"\n description = (\n \"Transforms LLM responses into **structured data formats**. Ideal for extracting specific information \"\n \"or creating consistent outputs.\"\n )\n icon = \"braces\"\n\n inputs = [\n HandleInput(\n name=\"llm\",\n display_name=\"Language Model\",\n info=\"The language model to use to generate the structured output.\",\n input_types=[\"LanguageModel\"],\n ),\n MessageTextInput(name=\"input_value\", display_name=\"Input message\"),\n StrInput(\n name=\"schema_name\",\n display_name=\"Schema Name\",\n info=\"Provide a name for the output data schema.\",\n ),\n TableInput(\n name=\"output_schema\",\n display_name=\"Output Schema\",\n info=\"Define the structure and data types for the model's output.\",\n table_schema=[\n {\n \"name\": \"name\",\n \"display_name\": \"Name\",\n \"type\": \"str\",\n \"description\": \"Specify the name of the output field.\",\n \"default\": \"field\",\n },\n {\n \"name\": \"description\",\n \"display_name\": \"Description\",\n \"type\": \"str\",\n \"description\": \"Describe the purpose of the output field.\",\n \"default\": \"description of field\",\n },\n {\n \"name\": \"type\",\n \"display_name\": \"Type\",\n \"type\": \"str\",\n \"description\": (\n \"Indicate the data type of the output field (e.g., str, int, float, bool, list, dict).\"\n ),\n \"default\": \"text\",\n },\n {\n \"name\": \"multiple\",\n \"display_name\": \"Multiple\",\n \"type\": \"boolean\",\n \"description\": \"Set to True if this output field should be a list of the specified type.\",\n \"default\": \"False\",\n },\n ],\n value=[{\"name\": \"field\", \"description\": \"description of field\", \"type\": \"text\", \"multiple\": \"False\"}],\n ),\n BoolInput(\n name=\"multiple\",\n display_name=\"Generate Multiple\",\n info=\"Set to True if the model should generate a list of outputs instead of a single output.\",\n ),\n ]\n\n outputs = [\n Output(name=\"structured_output\", display_name=\"Structured Output\", method=\"build_structured_output\"),\n ]\n\n def build_structured_output(self) -> Data:\n if not hasattr(self.llm, \"with_structured_output\"):\n msg = \"Language model does not support structured output.\"\n raise TypeError(msg)\n if not self.output_schema:\n msg = \"Output schema cannot be empty\"\n raise ValueError(msg)\n\n output_model_ = build_model_from_schema(self.output_schema)\n if self.multiple:\n output_model = create_model(\n self.schema_name,\n objects=(list[output_model_], Field(description=f\"A list of {self.schema_name}.\")), # type: ignore[valid-type]\n )\n else:\n output_model = output_model_\n try:\n llm_with_structured_output = cast(\"LanguageModel\", self.llm).with_structured_output(schema=output_model) # type: ignore[valid-type, attr-defined]\n\n except NotImplementedError as exc:\n msg = f\"{self.llm.__class__.__name__} does not support structured output.\"\n raise TypeError(msg) from exc\n config_dict = {\n \"run_name\": self.display_name,\n \"project_name\": self.get_project_name(),\n \"callbacks\": self.get_langchain_callbacks(),\n }\n output = get_chat_result(runnable=llm_with_structured_output, input_value=self.input_value, config=config_dict)\n if isinstance(output, BaseModel):\n output_dict = output.model_dump()\n else:\n msg = f\"Output should be a Pydantic BaseModel, got {type(output)} ({output})\"\n raise TypeError(msg)\n return Data(data=output_dict)\n" + "value": "from typing import TYPE_CHECKING, cast\n\nfrom pydantic import BaseModel, Field, create_model\n\nfrom langflow.base.models.chat_result import get_chat_result\nfrom langflow.custom import Component\nfrom langflow.helpers.base_model import build_model_from_schema\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TableInput,\n)\nfrom langflow.schema.data import Data\nfrom langflow.schema.dataframe import DataFrame\nfrom langflow.schema.table import EditMode\n\nif TYPE_CHECKING:\n from langflow.field_typing.constants import LanguageModel\n\n\nclass StructuredOutputComponent(Component):\n display_name = \"Structured Output\"\n description = (\n \"Transforms LLM responses into **structured data formats**. Ideal for extracting specific information \"\n \"or creating consistent outputs.\"\n )\n name = \"StructuredOutput\"\n icon = \"braces\"\n\n inputs = [\n HandleInput(\n name=\"llm\",\n display_name=\"Language Model\",\n info=\"The language model to use to generate the structured output.\",\n input_types=[\"LanguageModel\"],\n required=True,\n ),\n MessageTextInput(\n name=\"input_value\",\n display_name=\"Input Message\",\n info=\"The input message to the language model.\",\n tool_mode=True,\n required=True,\n ),\n MultilineInput(\n name=\"system_prompt\",\n display_name=\"Format Instructions\",\n info=\"The instructions to the language model for formatting the output.\",\n value=(\n \"You are an AI system designed to extract structured information from unstructured text.\"\n \"Given the input_text, return a JSON object with predefined keys based on the expected structure.\"\n \"Extract values accurately and format them according to the specified type \"\n \"(e.g., string, integer, float, date).\"\n \"If a value is missing or cannot be determined, return a default \"\n \"(e.g., null, 0, or 'N/A').\"\n \"If multiple instances of the expected structure exist within the input_text, \"\n \"stream each as a separate JSON object.\"\n ),\n required=True,\n advanced=True,\n ),\n MessageTextInput(\n name=\"schema_name\",\n display_name=\"Schema Name\",\n info=\"Provide a name for the output data schema.\",\n advanced=True,\n ),\n TableInput(\n name=\"output_schema\",\n display_name=\"Output Schema\",\n info=\"Define the structure and data types for the model's output.\",\n required=True,\n # TODO: remove deault value\n table_schema=[\n {\n \"name\": \"name\",\n \"display_name\": \"Name\",\n \"type\": \"str\",\n \"description\": \"Specify the name of the output field.\",\n \"default\": \"field\",\n \"edit_mode\": EditMode.INLINE,\n },\n {\n \"name\": \"description\",\n \"display_name\": \"Description\",\n \"type\": \"str\",\n \"description\": \"Describe the purpose of the output field.\",\n \"default\": \"description of field\",\n \"edit_mode\": EditMode.POPOVER,\n },\n {\n \"name\": \"type\",\n \"display_name\": \"Type\",\n \"type\": \"str\",\n \"edit_mode\": EditMode.INLINE,\n \"description\": (\n \"Indicate the data type of the output field (e.g., str, int, float, bool, list, dict).\"\n ),\n \"options\": [\"str\", \"int\", \"float\", \"bool\", \"list\", \"dict\"],\n \"default\": \"str\",\n },\n {\n \"name\": \"multiple\",\n \"display_name\": \"Multiple\",\n \"type\": \"boolean\",\n \"description\": \"Set to True if this output field should be a list of the specified type.\",\n \"default\": \"False\",\n \"edit_mode\": EditMode.INLINE,\n },\n ],\n value=[\n {\n \"name\": \"field\",\n \"description\": \"description of field\",\n \"type\": \"str\",\n \"multiple\": \"False\",\n }\n ],\n ),\n BoolInput(\n name=\"multiple\",\n advanced=True,\n display_name=\"Generate Multiple\",\n info=\"[Deplrecated] Always set to True\",\n value=True,\n ),\n ]\n\n outputs = [\n Output(\n name=\"structured_output\",\n display_name=\"Structured Output\",\n method=\"build_structured_output\",\n ),\n Output(\n name=\"structured_output_dataframe\",\n display_name=\"DataFrame\",\n method=\"as_dataframe\",\n ),\n ]\n\n def build_structured_output_base(self) -> Data:\n schema_name = self.schema_name or \"OutputModel\"\n\n if not hasattr(self.llm, \"with_structured_output\"):\n msg = \"Language model does not support structured output.\"\n raise TypeError(msg)\n if not self.output_schema:\n msg = \"Output schema cannot be empty\"\n raise ValueError(msg)\n\n output_model_ = build_model_from_schema(self.output_schema)\n\n output_model = create_model(\n schema_name,\n objects=(list[output_model_], Field(description=f\"A list of {schema_name}.\")), # type: ignore[valid-type]\n )\n\n try:\n llm_with_structured_output = cast(\"LanguageModel\", self.llm).with_structured_output(schema=output_model) # type: ignore[valid-type, attr-defined]\n\n except NotImplementedError as exc:\n msg = f\"{self.llm.__class__.__name__} does not support structured output.\"\n raise TypeError(msg) from exc\n config_dict = {\n \"run_name\": self.display_name,\n \"project_name\": self.get_project_name(),\n \"callbacks\": self.get_langchain_callbacks(),\n }\n result = get_chat_result(\n runnable=llm_with_structured_output,\n system_message=self.system_prompt,\n input_value=self.input_value,\n config=config_dict,\n )\n if isinstance(result, BaseModel):\n result = result.model_dump()\n if \"objects\" in result:\n return result[\"objects\"]\n return result\n\n def build_structured_output(self) -> Data:\n output = self.build_structured_output_base()\n\n return Data(results=output)\n\n def as_dataframe(self) -> DataFrame:\n output = self.build_structured_output_base()\n if isinstance(output, list):\n return DataFrame(data=output)\n return DataFrame(data=[output])\n" }, "input_value": { "_input_type": "MessageTextInput", "advanced": false, - "display_name": "Input message", + "display_name": "Input Message", "dynamic": false, - "info": "", + "info": "The input message to the language model.", "input_types": [ "Message" ], "list": false, + "list_add_label": "Add More", "load_from_db": false, "name": "input_value", "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, - "tool_mode": false, + "tool_mode": true, "trace_as_input": true, "trace_as_metadata": true, "type": "str", @@ -978,9 +920,10 @@ "LanguageModel" ], "list": false, + "list_add_label": "Add More", "name": "llm", "placeholder": "", - "required": false, + "required": true, "show": true, "title_case": false, "trace_as_metadata": true, @@ -989,16 +932,19 @@ }, "multiple": { "_input_type": "BoolInput", - "advanced": false, + "advanced": true, "display_name": "Generate Multiple", "dynamic": false, - "info": "Set to True if the model should generate a list of outputs instead of a single output.", + "info": "[Deplrecated] Always set to True", "list": false, + "list_add_label": "Add More", + "load_from_db": false, "name": "multiple", "placeholder": "", "required": false, "show": true, "title_case": false, + "tool_mode": false, "trace_as_metadata": true, "type": "bool", "value": false @@ -1010,47 +956,71 @@ "dynamic": false, "info": "Define the structure and data types for the model's output.", "is_list": true, + "list_add_label": "Add More", "load_from_db": false, "name": "output_schema", "placeholder": "", - "required": false, + "required": true, "show": true, + "table_icon": "Table", "table_schema": { "columns": [ { + "default": "field", "description": "Specify the name of the output field.", + "disable_edit": false, "display_name": "Name", + "edit_mode": "inline", "filterable": true, "formatter": "text", + "hidden": false, "name": "name", "sortable": true, - "type": "text" + "type": "str" }, { + "default": "description of field", "description": "Describe the purpose of the output field.", + "disable_edit": false, "display_name": "Description", + "edit_mode": "popover", "filterable": true, "formatter": "text", + "hidden": false, "name": "description", "sortable": true, - "type": "text" + "type": "str" }, { - "default": "text", + "default": "str", "description": "Indicate the data type of the output field (e.g., str, int, float, bool, list, dict).", + "disable_edit": false, "display_name": "Type", + "edit_mode": "inline", "filterable": true, "formatter": "text", + "hidden": false, "name": "type", + "options": [ + "str", + "int", + "float", + "bool", + "list", + "dict" + ], "sortable": true, - "type": "text" + "type": "str" }, { - "default": "False", + "default": false, "description": "Set to True if this output field should be a list of the specified type.", + "disable_edit": false, "display_name": "Multiple", + "edit_mode": "inline", "filterable": true, - "formatter": "text", + "formatter": "boolean", + "hidden": false, "name": "multiple", "sortable": true, "type": "boolean" @@ -1058,7 +1028,10 @@ ] }, "title_case": false, + "tool_mode": false, "trace_as_metadata": true, + "trigger_icon": "Table", + "trigger_text": "Open table", "type": "table", "value": [ { @@ -1124,37 +1097,68 @@ ] }, "schema_name": { - "_input_type": "StrInput", - "advanced": false, + "_input_type": "MessageTextInput", + "advanced": true, "display_name": "Schema Name", "dynamic": false, "info": "Provide a name for the output data schema.", + "input_types": [ + "Message" + ], "list": false, + "list_add_label": "Add More", "load_from_db": false, "name": "schema_name", "placeholder": "", "required": false, "show": true, "title_case": false, + "tool_mode": false, + "trace_as_input": true, "trace_as_metadata": true, "type": "str", "value": "output_schema" + }, + "system_prompt": { + "_input_type": "MultilineInput", + "advanced": true, + "copy_field": false, + "display_name": "Format Instructions", + "dynamic": false, + "info": "The instructions to the language model for formatting the output.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "system_prompt", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "You are an AI system designed to extract structured information from unstructured text.Given the input_text, return a JSON object with predefined keys based on the expected structure.Extract values accurately and format them according to the specified type (e.g., string, integer, float, date).If a value is missing or cannot be determined, return a default (e.g., null, 0, or 'N/A').If multiple instances of the expected structure exist within the input_text, stream each as a separate JSON object." } }, "tool_mode": false }, - "type": "StructuredOutputComponent" + "type": "StructuredOutput" }, "dragging": false, "height": 541, - "id": "StructuredOutputComponent-HNJw1", + "id": "StructuredOutput-5OFKk", "measured": { "height": 541, "width": 320 }, "position": { "x": 1716.7237308033855, - "y": 459.2476214962564 + "y": 852.4871875579063 }, "positionAbsolute": { "x": 1770.7096106546323, @@ -1164,171 +1168,11 @@ "type": "genericNode", "width": 320 }, - { - "data": { - "id": "ParseData-7nw3f", - "node": { - "base_classes": [ - "Message" - ], - "beta": false, - "category": "helpers", - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert Data into plain text following a specified template.", - "display_name": "Parse Data", - "documentation": "", - "edited": false, - "field_order": [ - "data", - "template", - "sep" - ], - "frozen": false, - "icon": "message-square", - "key": "ParseData", - "legacy": false, - "lf_version": "1.1.1", - "metadata": { - "legacy_name": "Parse Data" - }, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Message", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - }, - { - "allows_loop": false, - "cache": true, - "display_name": "Data List", - "method": "parse_data_as_list", - "name": "data_list", - "selected": "Data", - "tool_mode": true, - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" - }, - "data": { - "_input_type": "DataInput", - "advanced": false, - "display_name": "Data", - "dynamic": false, - "info": "The data to convert to text.", - "input_types": [ - "Data" - ], - "list": true, - "name": "data", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "_input_type": "StrInput", - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "", - "list": false, - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "_input_type": "MultilineInput", - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template to use for formatting the data. It can contain the keys {text}, {data} or any other key in the Data.", - "input_types": [ - "Message" - ], - "list": false, - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "# Company Profile\n\n## Basic Information\n- **Domain:** {domain}\n- **LinkedIn URL:** {linkedinUrl}\n\n## Pricing and Plans\n- **Cheapest Plan:** {cheapestPlan}\n- **Has Free Trial:** {hasFreeTrial}\n- **Has Enterprise Plan:** {hasEnterprisePlan}\n\n## Technical Capabilities\n- **Has API:** {hasAPI}\n\n## Market and Target Audience\n- **Market:** {market}\n- **Target Industries:** {targetIndustries}\n\n## Pricing Structure\n{pricingTiers}\n\n## Key Features\n{KeyFeatures}\n" - } - } - }, - "type": "ParseData" - }, - "dragging": false, - "height": 302, - "id": "ParseData-7nw3f", - "measured": { - "height": 302, - "width": 320 - }, - "position": { - "x": 2139.05558520377, - "y": 780.6849187394922 - }, - "positionAbsolute": { - "x": 2139.05558520377, - "y": 780.6849187394922 - }, - "selected": false, - "type": "genericNode", - "width": 320 - }, { "data": { "description": "Define the agent's instructions, then enter a task to complete using tools.", "display_name": "Agent", - "id": "Agent-ZlvTd", + "id": "Agent-bjWdX", "node": { "base_classes": [ "Message" @@ -1371,7 +1215,7 @@ "frozen": false, "icon": "bot", "legacy": false, - "lf_version": "1.1.1", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -1478,7 +1322,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -1927,7 +1771,7 @@ }, "dragging": false, "height": 650, - "id": "Agent-ZlvTd", + "id": "Agent-bjWdX", "measured": { "height": 650, "width": 320 @@ -1940,43 +1784,11 @@ "type": "genericNode", "width": 320 }, - { - "data": { - "id": "note-p1p0l", - "node": { - "description": "# 🔑 Tavily AI Search Needs API Key\n\nYou can get 1000 searches/month free [here](https://tavily.com/) ", - "display_name": "", - "documentation": "", - "template": { - "backgroundColor": "lime" - } - }, - "type": "note" - }, - "dragging": false, - "height": 324, - "id": "note-p1p0l", - "measured": { - "height": 324, - "width": 325 - }, - "position": { - "x": 872.8795713635943, - "y": 628.4318648733362 - }, - "positionAbsolute": { - "x": 921.6062384772317, - "y": 642.1140062279873 - }, - "selected": false, - "type": "noteNode", - "width": 324 - }, { "data": { "description": "**Tavily AI** is a search engine optimized for LLMs and RAG, aimed at efficient, quick, and persistent search results.", "display_name": "Tavily AI Search", - "id": "TavilySearchComponent-Fl2MN", + "id": "TavilySearchComponent-vpPJd", "node": { "base_classes": [ "Data", @@ -2002,6 +1814,7 @@ "frozen": false, "icon": "TavilyIcon", "legacy": false, + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -2035,7 +1848,7 @@ "input_types": [ "Message" ], - "load_from_db": true, + "load_from_db": false, "name": "api_key", "password": true, "placeholder": "", @@ -2043,7 +1856,7 @@ "show": true, "title_case": false, "type": "str", - "value": "TAVILY_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -2328,7 +2141,7 @@ "type": "TavilySearchComponent" }, "dragging": false, - "id": "TavilySearchComponent-Fl2MN", + "id": "TavilySearchComponent-vpPJd", "measured": { "height": 437, "width": 320 @@ -2337,12 +2150,12 @@ "x": 875.7686789989679, "y": 798.478848045035 }, - "selected": true, + "selected": false, "type": "genericNode" }, { "data": { - "id": "OpenAIModel-GOv57", + "id": "OpenAIModel-2q7JZ", "node": { "base_classes": [ "LanguageModel", @@ -2373,6 +2186,7 @@ "icon": "OpenAI", "key": "OpenAIModel", "legacy": false, + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -2429,7 +2243,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -2710,28 +2524,202 @@ "type": "OpenAIModel" }, "dragging": false, - "id": "OpenAIModel-GOv57", + "id": "OpenAIModel-2q7JZ", "measured": { "height": 525, "width": 320 }, "position": { - "x": 1718.9581068990763, - "y": 1035.8255894745982 + "x": 1282.8196790852462, + "y": 1161.6622506143262 }, "selected": false, "type": "genericNode" + }, + { + "data": { + "id": "parser-7JQpB", + "node": { + "base_classes": [ + "Message" + ], + "beta": false, + "category": "processing", + "conditional_paths": [], + "custom_fields": {}, + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", + "documentation": "", + "edited": false, + "field_order": [ + "mode", + "pattern", + "input_data", + "sep" + ], + "frozen": false, + "icon": "braces", + "key": "parser", + "legacy": false, + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", + "selected": "Message", + "tool_mode": true, + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 2.220446049250313e-16, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n name = \"parser\"\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" + }, + "input_data": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Data or DataFrame", + "dynamic": false, + "info": "Accepts either a DataFrame or a Data object.", + "input_types": [ + "DataFrame", + "Data" + ], + "list": false, + "list_add_label": "Add More", + "name": "input_data", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Parser" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "# Company Profile\n\n## Basic Information\n- **Domain:** {domain}\n- **LinkedIn URL:** {linkedinUrl}\n\n## Pricing and Plans\n- **Cheapest Plan:** {cheapestPlan}\n- **Has Free Trial:** {hasFreeTrial}\n- **Has Enterprise Plan:** {hasEnterprisePlan}\n\n## Technical Capabilities\n- **Has API:** {hasAPI}\n\n## Market and Target Audience\n- **Market:** {market}\n- **Target Industries:** {targetIndustries}\n\n## Pricing Structure\n{pricingTiers}\n\n## Key Features\n{KeyFeatures}\n" + }, + "sep": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Separator", + "dynamic": false, + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "sep", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "\n" + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "parser" + }, + "dragging": false, + "id": "parser-7JQpB", + "measured": { + "height": 395, + "width": 320 + }, + "position": { + "x": 2132.7576351687417, + "y": 744.0431534971781 + }, + "selected": true, + "type": "genericNode" } ], "viewport": { - "x": -58.50231656538608, - "y": 29.06216478820238, - "zoom": 0.5075901953862927 + "x": 218.73749848572567, + "y": 82.09531548995307, + "zoom": 0.3869462183165413 } }, "description": "Researches companies, extracts key business data, and presents structured information for efficient analysis. ", "endpoint_name": null, - "id": "8944aed3-aa86-4c50-b725-5a4a3973ba5a", + "id": "312739e7-29bb-4a71-8faf-3bcf2d7c22bb", "is_component": false, "last_tested_version": "1.2.0", "name": "Market Research", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json b/src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json index 9657d4942..82787062c 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json @@ -1,70 +1,13 @@ { "data": { "edges": [ - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "AssemblyAITranscriptionJobPoller", - "id": "AssemblyAITranscriptionJobPoller-nNPur", - "name": "transcription_result", - "output_types": [ - "Data" - ] - }, - "targetHandle": { - "fieldName": "data", - "id": "ParseData-g3zYs", - "inputTypes": [ - "Data" - ], - "type": "other" - } - }, - "id": "reactflow__edge-AssemblyAITranscriptionJobPoller-nNPur{œdataTypeœ:œAssemblyAITranscriptionJobPollerœ,œidœ:œAssemblyAITranscriptionJobPoller-nNPurœ,œnameœ:œtranscription_resultœ,œoutput_typesœ:[œDataœ]}-ParseData-g3zYs{œfieldNameœ:œdataœ,œidœ:œParseData-g3zYsœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", - "selected": false, - "source": "AssemblyAITranscriptionJobPoller-nNPur", - "sourceHandle": "{œdataTypeœ: œAssemblyAITranscriptionJobPollerœ, œidœ: œAssemblyAITranscriptionJobPoller-nNPurœ, œnameœ: œtranscription_resultœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-g3zYs", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-g3zYsœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-g3zYs", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "transcript", - "id": "Prompt-c1TAK", - "inputTypes": [ - "Message", - "Text" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-g3zYs{œdataTypeœ:œParseDataœ,œidœ:œParseData-g3zYsœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-Prompt-c1TAK{œfieldNameœ:œtranscriptœ,œidœ:œPrompt-c1TAKœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-g3zYs", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-g3zYsœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-c1TAK", - "targetHandle": "{œfieldNameœ: œtranscriptœ, œidœ: œPrompt-c1TAKœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" - }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "Prompt", - "id": "Prompt-c1TAK", + "id": "Prompt-5Y1de", "name": "prompt", "output_types": [ "Message" @@ -72,19 +15,19 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "OpenAIModel-XBy5M", + "id": "OpenAIModel-ac6TO", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-Prompt-c1TAK{œdataTypeœ:œPromptœ,œidœ:œPrompt-c1TAKœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-XBy5M{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-XBy5Mœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-5Y1de{œdataTypeœ:œPromptœ,œidœ:œPrompt-5Y1deœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-ac6TO{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-ac6TOœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Prompt-c1TAK", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-c1TAKœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-XBy5M", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-XBy5Mœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "Prompt-5Y1de", + "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-5Y1deœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-ac6TO", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-ac6TOœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -92,7 +35,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-XBy5M", + "id": "OpenAIModel-ac6TO", "name": "text_output", "output_types": [ "Message" @@ -100,7 +43,7 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-mcuWI", + "id": "ChatOutput-g8PGI", "inputTypes": [ "Data", "DataFrame", @@ -109,42 +52,12 @@ "type": "str" } }, - "id": "reactflow__edge-OpenAIModel-XBy5M{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-XBy5Mœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-mcuWI{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-mcuWIœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-OpenAIModel-ac6TO{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-ac6TOœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-g8PGI{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-g8PGIœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "OpenAIModel-XBy5M", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-XBy5Mœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-mcuWI", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-mcuWIœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-g3zYs", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "ChatOutput-2BqOF", - "inputTypes": [ - "Data", - "DataFrame", - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-g3zYs{œdataTypeœ:œParseDataœ,œidœ:œParseData-g3zYsœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-2BqOF{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-2BqOFœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-g3zYs", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-g3zYsœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-2BqOF", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-2BqOFœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" + "source": "OpenAIModel-ac6TO", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-ac6TOœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-g8PGI", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-g8PGIœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -152,7 +65,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-r5JLB", + "id": "OpenAIModel-t3KLO", "name": "text_output", "output_types": [ "Message" @@ -160,7 +73,7 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-ADcYl", + "id": "ChatOutput-r8oga", "inputTypes": [ "Data", "DataFrame", @@ -169,12 +82,12 @@ "type": "str" } }, - "id": "reactflow__edge-OpenAIModel-r5JLB{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-r5JLBœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-ADcYl{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-ADcYlœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-OpenAIModel-t3KLO{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-t3KLOœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-r8oga{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-r8ogaœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "OpenAIModel-r5JLB", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-r5JLBœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-ADcYl", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-ADcYlœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" + "source": "OpenAIModel-t3KLO", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-t3KLOœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-r8oga", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-r8ogaœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -182,7 +95,7 @@ "data": { "sourceHandle": { "dataType": "Memory", - "id": "Memory-waylX", + "id": "Memory-9SYWU", "name": "messages_text", "output_types": [ "Message" @@ -190,7 +103,7 @@ }, "targetHandle": { "fieldName": "history", - "id": "Prompt-phxgr", + "id": "Prompt-7sDZ1", "inputTypes": [ "Message", "Text" @@ -198,12 +111,12 @@ "type": "str" } }, - "id": "reactflow__edge-Memory-waylX{œdataTypeœ:œMemoryœ,œidœ:œMemory-waylXœ,œnameœ:œmessages_textœ,œoutput_typesœ:[œMessageœ]}-Prompt-phxgr{œfieldNameœ:œhistoryœ,œidœ:œPrompt-phxgrœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Memory-9SYWU{œdataTypeœ:œMemoryœ,œidœ:œMemory-9SYWUœ,œnameœ:œmessages_textœ,œoutput_typesœ:[œMessageœ]}-Prompt-7sDZ1{œfieldNameœ:œhistoryœ,œidœ:œPrompt-7sDZ1œ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", "selected": false, - "source": "Memory-waylX", - "sourceHandle": "{œdataTypeœ: œMemoryœ, œidœ: œMemory-waylXœ, œnameœ: œmessages_textœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-phxgr", - "targetHandle": "{œfieldNameœ: œhistoryœ, œidœ: œPrompt-phxgrœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" + "source": "Memory-9SYWU", + "sourceHandle": "{œdataTypeœ: œMemoryœ, œidœ: œMemory-9SYWUœ, œnameœ: œmessages_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-7sDZ1", + "targetHandle": "{œfieldNameœ: œhistoryœ, œidœ: œPrompt-7sDZ1œ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -211,7 +124,7 @@ "data": { "sourceHandle": { "dataType": "ChatInput", - "id": "ChatInput-JytcD", + "id": "ChatInput-2fdX6", "name": "message", "output_types": [ "Message" @@ -219,7 +132,7 @@ }, "targetHandle": { "fieldName": "input", - "id": "Prompt-phxgr", + "id": "Prompt-7sDZ1", "inputTypes": [ "Message", "Text" @@ -227,12 +140,12 @@ "type": "str" } }, - "id": "reactflow__edge-ChatInput-JytcD{œdataTypeœ:œChatInputœ,œidœ:œChatInput-JytcDœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Prompt-phxgr{œfieldNameœ:œinputœ,œidœ:œPrompt-phxgrœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-2fdX6{œdataTypeœ:œChatInputœ,œidœ:œChatInput-2fdX6œ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Prompt-7sDZ1{œfieldNameœ:œinputœ,œidœ:œPrompt-7sDZ1œ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", "selected": false, - "source": "ChatInput-JytcD", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-JytcDœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-phxgr", - "targetHandle": "{œfieldNameœ: œinputœ, œidœ: œPrompt-phxgrœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" + "source": "ChatInput-2fdX6", + "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-2fdX6œ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-7sDZ1", + "targetHandle": "{œfieldNameœ: œinputœ, œidœ: œPrompt-7sDZ1œ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -240,7 +153,7 @@ "data": { "sourceHandle": { "dataType": "Prompt", - "id": "Prompt-phxgr", + "id": "Prompt-7sDZ1", "name": "prompt", "output_types": [ "Message" @@ -248,19 +161,19 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "OpenAIModel-r5JLB", + "id": "OpenAIModel-t3KLO", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-Prompt-phxgr{œdataTypeœ:œPromptœ,œidœ:œPrompt-phxgrœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-r5JLB{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-r5JLBœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-7sDZ1{œdataTypeœ:œPromptœ,œidœ:œPrompt-7sDZ1œ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-t3KLO{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-t3KLOœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Prompt-phxgr", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-phxgrœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-r5JLB", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-r5JLBœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "Prompt-7sDZ1", + "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-7sDZ1œ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-t3KLO", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-t3KLOœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -268,7 +181,7 @@ "data": { "sourceHandle": { "dataType": "AssemblyAITranscriptionJobCreator", - "id": "AssemblyAITranscriptionJobCreator-8EJx8", + "id": "AssemblyAITranscriptionJobCreator-qtRiO", "name": "transcript_id", "output_types": [ "Data" @@ -276,25 +189,106 @@ }, "targetHandle": { "fieldName": "transcript_id", - "id": "AssemblyAITranscriptionJobPoller-nNPur", + "id": "AssemblyAITranscriptionJobPoller-wdb3c", "inputTypes": [ "Data" ], "type": "other" } }, - "id": "reactflow__edge-AssemblyAITranscriptionJobCreator-8EJx8{œdataTypeœ:œAssemblyAITranscriptionJobCreatorœ,œidœ:œAssemblyAITranscriptionJobCreator-8EJx8œ,œnameœ:œtranscript_idœ,œoutput_typesœ:[œDataœ]}-AssemblyAITranscriptionJobPoller-nNPur{œfieldNameœ:œtranscript_idœ,œidœ:œAssemblyAITranscriptionJobPoller-nNPurœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-AssemblyAITranscriptionJobCreator-qtRiO{œdataTypeœ:œAssemblyAITranscriptionJobCreatorœ,œidœ:œAssemblyAITranscriptionJobCreator-qtRiOœ,œnameœ:œtranscript_idœ,œoutput_typesœ:[œDataœ]}-AssemblyAITranscriptionJobPoller-wdb3c{œfieldNameœ:œtranscript_idœ,œidœ:œAssemblyAITranscriptionJobPoller-wdb3cœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", "selected": false, - "source": "AssemblyAITranscriptionJobCreator-8EJx8", - "sourceHandle": "{œdataTypeœ: œAssemblyAITranscriptionJobCreatorœ, œidœ: œAssemblyAITranscriptionJobCreator-8EJx8œ, œnameœ: œtranscript_idœ, œoutput_typesœ: [œDataœ]}", - "target": "AssemblyAITranscriptionJobPoller-nNPur", - "targetHandle": "{œfieldNameœ: œtranscript_idœ, œidœ: œAssemblyAITranscriptionJobPoller-nNPurœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" + "source": "AssemblyAITranscriptionJobCreator-qtRiO", + "sourceHandle": "{œdataTypeœ: œAssemblyAITranscriptionJobCreatorœ, œidœ: œAssemblyAITranscriptionJobCreator-qtRiOœ, œnameœ: œtranscript_idœ, œoutput_typesœ: [œDataœ]}", + "target": "AssemblyAITranscriptionJobPoller-wdb3c", + "targetHandle": "{œfieldNameœ: œtranscript_idœ, œidœ: œAssemblyAITranscriptionJobPoller-wdb3cœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "data": { + "sourceHandle": { + "dataType": "AssemblyAITranscriptionJobPoller", + "id": "AssemblyAITranscriptionJobPoller-wdb3c", + "name": "transcription_result", + "output_types": [ + "Data" + ] + }, + "targetHandle": { + "fieldName": "input_data", + "id": "parser-7Q6Sz", + "inputTypes": [ + "DataFrame", + "Data" + ], + "type": "other" + } + }, + "id": "xy-edge__AssemblyAITranscriptionJobPoller-wdb3c{œdataTypeœ:œAssemblyAITranscriptionJobPollerœ,œidœ:œAssemblyAITranscriptionJobPoller-wdb3cœ,œnameœ:œtranscription_resultœ,œoutput_typesœ:[œDataœ]}-parser-7Q6Sz{œfieldNameœ:œinput_dataœ,œidœ:œparser-7Q6Szœ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", + "selected": false, + "source": "AssemblyAITranscriptionJobPoller-wdb3c", + "sourceHandle": "{œdataTypeœ: œAssemblyAITranscriptionJobPollerœ, œidœ: œAssemblyAITranscriptionJobPoller-wdb3cœ, œnameœ: œtranscription_resultœ, œoutput_typesœ: [œDataœ]}", + "target": "parser-7Q6Sz", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-7Q6Szœ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" + }, + { + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-7Q6Sz", + "name": "parsed_text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "transcript", + "id": "Prompt-5Y1de", + "inputTypes": [ + "Message", + "Text" + ], + "type": "str" + } + }, + "id": "xy-edge__parser-7Q6Sz{œdataTypeœ:œparserœ,œidœ:œparser-7Q6Szœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-Prompt-5Y1de{œfieldNameœ:œtranscriptœ,œidœ:œPrompt-5Y1deœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "source": "parser-7Q6Sz", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-7Q6Szœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-5Y1de", + "targetHandle": "{œfieldNameœ: œtranscriptœ, œidœ: œPrompt-5Y1deœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" + }, + { + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-7Q6Sz", + "name": "parsed_text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "ChatOutput-AZKHq", + "inputTypes": [ + "Data", + "DataFrame", + "Message" + ], + "type": "str" + } + }, + "id": "xy-edge__parser-7Q6Sz{œdataTypeœ:œparserœ,œidœ:œparser-7Q6Szœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-AZKHq{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-AZKHqœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "source": "parser-7Q6Sz", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-7Q6Szœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-AZKHq", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-AZKHqœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" } ], "nodes": [ { "data": { - "id": "AssemblyAITranscriptionJobPoller-nNPur", + "id": "AssemblyAITranscriptionJobPoller-wdb3c", "node": { "base_classes": [ "Data" @@ -345,7 +339,7 @@ "input_types": [ "Message" ], - "load_from_db": true, + "load_from_db": false, "name": "api_key", "password": true, "placeholder": "", @@ -353,7 +347,7 @@ "show": true, "title_case": false, "type": "str", - "value": "ASSEMBLY_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -425,7 +419,7 @@ "showNode": true, "type": "AssemblyAITranscriptionJobPoller" }, - "id": "AssemblyAITranscriptionJobPoller-nNPur", + "id": "AssemblyAITranscriptionJobPoller-wdb3c", "measured": { "height": 294, "width": 320 @@ -434,173 +428,12 @@ "x": 943.468098795128, "y": 282.3188316337007 }, - "selected": true, - "type": "genericNode" - }, - { - "data": { - "id": "ParseData-g3zYs", - "node": { - "base_classes": [ - "Data", - "Message" - ], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert Data objects into Messages using any {field_name} from input data.", - "display_name": "Data to Message", - "documentation": "", - "edited": false, - "field_order": [ - "data", - "template", - "sep" - ], - "frozen": false, - "icon": "message-square", - "legacy": false, - "lf_version": "1.1.5", - "metadata": { - "legacy_name": "Parse Data" - }, - "minimized": false, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Message", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - }, - { - "allows_loop": false, - "cache": true, - "display_name": "Data List", - "method": "parse_data_as_list", - "name": "data_list", - "selected": "Data", - "tool_mode": true, - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" - }, - "data": { - "_input_type": "DataInput", - "advanced": false, - "display_name": "Data", - "dynamic": false, - "info": "The data to convert to text.", - "input_types": [ - "Data" - ], - "list": true, - "list_add_label": "Add More", - "name": "data", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "_input_type": "StrInput", - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "", - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "_input_type": "MultilineInput", - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template to use for formatting the data. It can contain the keys {text}, {data} or any other key in the Data.", - "input_types": [ - "Message" - ], - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "{text}" - } - }, - "tool_mode": false - }, - "showNode": true, - "type": "ParseData" - }, - "id": "ParseData-g3zYs", - "measured": { - "height": 342, - "width": 320 - }, - "position": { - "x": 1330.927281184057, - "y": 382.3516758942169 - }, "selected": false, "type": "genericNode" }, { "data": { - "id": "OpenAIModel-XBy5M", + "id": "OpenAIModel-ac6TO", "node": { "base_classes": [ "LanguageModel", @@ -687,7 +520,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -967,7 +800,7 @@ "showNode": true, "type": "OpenAIModel" }, - "id": "OpenAIModel-XBy5M", + "id": "OpenAIModel-ac6TO", "measured": { "height": 525, "width": 320 @@ -981,7 +814,7 @@ }, { "data": { - "id": "Prompt-c1TAK", + "id": "Prompt-5Y1de", "node": { "base_classes": [ "Message" @@ -1118,7 +951,7 @@ "showNode": true, "type": "Prompt" }, - "id": "Prompt-c1TAK", + "id": "Prompt-5Y1de", "measured": { "height": 413, "width": 320 @@ -1132,7 +965,7 @@ }, { "data": { - "id": "ChatOutput-mcuWI", + "id": "ChatOutput-g8PGI", "node": { "base_classes": [ "Message" @@ -1419,7 +1252,7 @@ "showNode": true, "type": "ChatOutput" }, - "id": "ChatOutput-mcuWI", + "id": "ChatOutput-g8PGI", "measured": { "height": 230, "width": 320 @@ -1433,7 +1266,7 @@ }, { "data": { - "id": "ChatOutput-2BqOF", + "id": "ChatOutput-AZKHq", "node": { "base_classes": [ "Message" @@ -1720,7 +1553,7 @@ "showNode": false, "type": "ChatOutput" }, - "id": "ChatOutput-2BqOF", + "id": "ChatOutput-AZKHq", "measured": { "height": 66, "width": 192 @@ -1734,7 +1567,7 @@ }, { "data": { - "id": "OpenAIModel-r5JLB", + "id": "OpenAIModel-t3KLO", "node": { "base_classes": [ "LanguageModel", @@ -1821,7 +1654,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -2101,7 +1934,7 @@ "showNode": true, "type": "OpenAIModel" }, - "id": "OpenAIModel-r5JLB", + "id": "OpenAIModel-t3KLO", "measured": { "height": 525, "width": 320 @@ -2115,7 +1948,7 @@ }, { "data": { - "id": "ChatOutput-ADcYl", + "id": "ChatOutput-r8oga", "node": { "base_classes": [ "Message" @@ -2402,7 +2235,7 @@ "showNode": false, "type": "ChatOutput" }, - "id": "ChatOutput-ADcYl", + "id": "ChatOutput-r8oga", "measured": { "height": 66, "width": 192 @@ -2416,7 +2249,7 @@ }, { "data": { - "id": "Prompt-phxgr", + "id": "Prompt-7sDZ1", "node": { "base_classes": [ "Message" @@ -2577,7 +2410,7 @@ "showNode": true, "type": "Prompt" }, - "id": "Prompt-phxgr", + "id": "Prompt-7sDZ1", "measured": { "height": 465, "width": 320 @@ -2591,7 +2424,7 @@ }, { "data": { - "id": "Memory-waylX", + "id": "Memory-9SYWU", "node": { "base_classes": [ "Data", @@ -2843,7 +2676,7 @@ "showNode": true, "type": "Memory" }, - "id": "Memory-waylX", + "id": "Memory-9SYWU", "measured": { "height": 308, "width": 320 @@ -2857,7 +2690,7 @@ }, { "data": { - "id": "ChatInput-JytcD", + "id": "ChatInput-2fdX6", "node": { "base_classes": [ "Message" @@ -3141,7 +2974,7 @@ "showNode": false, "type": "ChatInput" }, - "id": "ChatInput-JytcD", + "id": "ChatInput-2fdX6", "measured": { "height": 66, "width": 192 @@ -3155,7 +2988,7 @@ }, { "data": { - "id": "note-3t3bj", + "id": "note-OELAf", "node": { "description": "### 💡 Add your Assembly AI API key and audio file here", "display_name": "", @@ -3168,7 +3001,7 @@ }, "dragging": false, "height": 324, - "id": "note-3t3bj", + "id": "note-OELAf", "measured": { "height": 324, "width": 455 @@ -3184,7 +3017,7 @@ }, { "data": { - "id": "note-sV2wq", + "id": "note-IrqOd", "node": { "description": "### 💡 Add your Assembly AI API key here", "display_name": "", @@ -3197,7 +3030,7 @@ }, "dragging": false, "height": 324, - "id": "note-sV2wq", + "id": "note-IrqOd", "measured": { "height": 324, "width": 364 @@ -3213,7 +3046,7 @@ }, { "data": { - "id": "note-zEnXR", + "id": "note-Yuc3u", "node": { "description": "### 💡 Add your OpenAI API key here", "display_name": "", @@ -3226,7 +3059,7 @@ }, "dragging": false, "height": 324, - "id": "note-zEnXR", + "id": "note-Yuc3u", "measured": { "height": 324, "width": 334 @@ -3242,7 +3075,7 @@ }, { "data": { - "id": "note-TQJ07", + "id": "note-8CPpJ", "node": { "description": "### 💡 Add your OpenAI API key here", "display_name": "", @@ -3254,7 +3087,7 @@ "type": "note" }, "dragging": false, - "id": "note-TQJ07", + "id": "note-8CPpJ", "measured": { "height": 324, "width": 324 @@ -3268,7 +3101,7 @@ }, { "data": { - "id": "AssemblyAITranscriptionJobCreator-8EJx8", + "id": "AssemblyAITranscriptionJobCreator-qtRiO", "node": { "base_classes": [ "Data" @@ -3328,7 +3161,7 @@ "input_types": [ "Message" ], - "load_from_db": true, + "load_from_db": false, "name": "api_key", "password": true, "placeholder": "", @@ -3336,7 +3169,7 @@ "show": true, "title_case": false, "type": "str", - "value": "ASSEMBLY_API_KEY" + "value": "" }, "audio_file": { "_input_type": "FileInput", @@ -3586,7 +3419,7 @@ "type": "AssemblyAITranscriptionJobCreator" }, "dragging": false, - "id": "AssemblyAITranscriptionJobCreator-8EJx8", + "id": "AssemblyAITranscriptionJobCreator-qtRiO", "measured": { "height": 385, "width": 320 @@ -3600,7 +3433,7 @@ }, { "data": { - "id": "note-fy6aG", + "id": "note-VaF3v", "node": { "description": "# Meeting Summary Generator\n\nThis flow automatically transcribes and summarizes meetings by converting audio recordings into concise summaries using **AssemblyAI** and **OpenAI GPT-4**. \n\n## Prerequisites\n\n- **[AssemblyAI API Key](https://www.assemblyai.com/)**\n- **[OpenAI API Key](https://platform.openai.com/)**\n\n## Quickstart\n\n1. Upload an audio file. Most common audio file formats are [supported](https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/components/assemblyai/assemblyai_start_transcript.py#L27).\n2. To run the summary generator flow, click **Playground**.\n\nThe flow transcribes the audio using **AssemblyAI**.\nThe transcript is formatted for AI processing.\nThe **GPT-4** model extracts key points and insights.\nThe summarized meeting details are displayed in a chat-friendly format.\n\n\n\n", "display_name": "", @@ -3611,7 +3444,7 @@ }, "dragging": false, "height": 612, - "id": "note-fy6aG", + "id": "note-VaF3v", "measured": { "height": 612, "width": 549 @@ -3624,17 +3457,191 @@ "selected": false, "type": "noteNode", "width": 548 + }, + { + "data": { + "id": "parser-7Q6Sz", + "node": { + "base_classes": [ + "Message" + ], + "beta": false, + "category": "processing", + "conditional_paths": [], + "custom_fields": {}, + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", + "documentation": "", + "edited": false, + "field_order": [ + "mode", + "pattern", + "input_data", + "sep" + ], + "frozen": false, + "icon": "braces", + "key": "parser", + "legacy": false, + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", + "selected": "Message", + "tool_mode": true, + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 2.220446049250313e-16, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n name = \"parser\"\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" + }, + "input_data": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Data or DataFrame", + "dynamic": false, + "info": "Accepts either a DataFrame or a Data object.", + "input_types": [ + "DataFrame", + "Data" + ], + "list": false, + "list_add_label": "Add More", + "name": "input_data", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Parser" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "Text: {text}" + }, + "sep": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Separator", + "dynamic": false, + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "sep", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "\n" + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "parser" + }, + "dragging": false, + "id": "parser-7Q6Sz", + "measured": { + "height": 395, + "width": 320 + }, + "position": { + "x": 1335.003903610802, + "y": 362.22452849075586 + }, + "selected": true, + "type": "genericNode" } ], "viewport": { - "x": 121.7090229089714, - "y": 8.227468658221653, - "zoom": 0.4336936257603202 + "x": 67.35579508773748, + "y": 126.4630908919309, + "zoom": 0.3907435802257692 } }, "description": "An AI-powered meeting summary generator that transcribes and summarizes meetings using AssemblyAI and OpenAI for quick insights.", "endpoint_name": null, - "id": "23f56532-73ca-44d3-9907-fb324d0a4ade", + "id": "3ea130e1-2054-4a51-8fff-9d9bfc8a7947", "is_component": false, "last_tested_version": "1.2.0", "name": "Meeting Summary", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json b/src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json index ced8fa539..7cef8db3b 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json @@ -1,41 +1,13 @@ { "data": { "edges": [ - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-uKULv", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "AnthropicModel-vog1V", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-uKULv{œdataTypeœ:œParseDataœ,œidœ:œParseData-uKULvœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-AnthropicModel-vog1V{œfieldNameœ:œinput_valueœ,œidœ:œAnthropicModel-vog1Vœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-uKULv", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-uKULvœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "AnthropicModel-vog1V", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAnthropicModel-vog1Vœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "TextInput", - "id": "TextInput-FRxv5", + "id": "TextInput-WR8cL", "name": "text", "output_types": [ "Message" @@ -43,19 +15,19 @@ }, "targetHandle": { "fieldName": "system_message", - "id": "AnthropicModel-vog1V", + "id": "AnthropicModel-tZx4n", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-TextInput-FRxv5{œdataTypeœ:œTextInputœ,œidœ:œTextInput-FRxv5œ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-AnthropicModel-vog1V{œfieldNameœ:œsystem_messageœ,œidœ:œAnthropicModel-vog1Vœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-TextInput-WR8cL{œdataTypeœ:œTextInputœ,œidœ:œTextInput-WR8cLœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-AnthropicModel-tZx4n{œfieldNameœ:œsystem_messageœ,œidœ:œAnthropicModel-tZx4nœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "TextInput-FRxv5", - "sourceHandle": "{œdataTypeœ: œTextInputœ, œidœ: œTextInput-FRxv5œ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "AnthropicModel-vog1V", - "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œAnthropicModel-vog1Vœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "TextInput-WR8cL", + "sourceHandle": "{œdataTypeœ: œTextInputœ, œidœ: œTextInput-WR8cLœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", + "target": "AnthropicModel-tZx4n", + "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œAnthropicModel-tZx4nœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -63,7 +35,92 @@ "data": { "sourceHandle": { "dataType": "AnthropicModel", - "id": "AnthropicModel-vog1V", + "id": "AnthropicModel-fz6rd", + "name": "model_output", + "output_types": [ + "LanguageModel" + ] + }, + "targetHandle": { + "fieldName": "llm", + "id": "StructuredOutput-tWLRa", + "inputTypes": [ + "LanguageModel" + ], + "type": "other" + } + }, + "id": "reactflow__edge-AnthropicModel-fz6rd{œdataTypeœ:œAnthropicModelœ,œidœ:œAnthropicModel-fz6rdœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutput-tWLRa{œfieldNameœ:œllmœ,œidœ:œStructuredOutput-tWLRaœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", + "selected": false, + "source": "AnthropicModel-fz6rd", + "sourceHandle": "{œdataTypeœ: œAnthropicModelœ, œidœ: œAnthropicModel-fz6rdœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", + "target": "StructuredOutput-tWLRa", + "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œStructuredOutput-tWLRaœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "ParserComponent", + "id": "ParserComponent-wrPyP", + "name": "parsed_text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "StructuredOutput-tWLRa", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "reactflow__edge-ParserComponent-wrPyP{œdataTypeœ:œParserComponentœ,œidœ:œParserComponent-wrPyPœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-StructuredOutput-tWLRa{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutput-tWLRaœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "ParserComponent-wrPyP", + "sourceHandle": "{œdataTypeœ: œParserComponentœ, œidœ: œParserComponent-wrPyPœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "StructuredOutput-tWLRa", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œStructuredOutput-tWLRaœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "File", + "id": "File-v8ouW", + "name": "dataframe", + "output_types": [ + "DataFrame" + ] + }, + "targetHandle": { + "fieldName": "input_data", + "id": "ParserComponent-wrPyP", + "inputTypes": [ + "DataFrame", + "Data" + ], + "type": "other" + } + }, + "id": "reactflow__edge-File-v8ouW{œdataTypeœ:œFileœ,œidœ:œFile-v8ouWœ,œnameœ:œdataframeœ,œoutput_typesœ:[œDataFrameœ]}-ParserComponent-wrPyP{œfieldNameœ:œinput_dataœ,œidœ:œParserComponent-wrPyPœ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", + "selected": false, + "source": "File-v8ouW", + "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-v8ouWœ, œnameœ: œdataframeœ, œoutput_typesœ: [œDataFrameœ]}", + "target": "ParserComponent-wrPyP", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œParserComponent-wrPyPœ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "AnthropicModel", + "id": "AnthropicModel-tZx4n", "name": "text_output", "output_types": [ "Message" @@ -71,7 +128,7 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-vpJbx", + "id": "ChatOutput-iLekZ", "inputTypes": [ "Data", "DataFrame", @@ -80,96 +137,12 @@ "type": "str" } }, - "id": "reactflow__edge-AnthropicModel-vog1V{œdataTypeœ:œAnthropicModelœ,œidœ:œAnthropicModel-vog1Vœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-vpJbx{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-vpJbxœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-AnthropicModel-tZx4n{œdataTypeœ:œAnthropicModelœ,œidœ:œAnthropicModel-tZx4nœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-iLekZ{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-iLekZœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "AnthropicModel-vog1V", - "sourceHandle": "{œdataTypeœ: œAnthropicModelœ, œidœ: œAnthropicModel-vog1Vœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-vpJbx", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-vpJbxœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "AnthropicModel", - "id": "AnthropicModel-5piN6", - "name": "model_output", - "output_types": [ - "LanguageModel" - ] - }, - "targetHandle": { - "fieldName": "llm", - "id": "StructuredOutput-ApbKx", - "inputTypes": [ - "LanguageModel" - ], - "type": "other" - } - }, - "id": "reactflow__edge-AnthropicModel-5piN6{œdataTypeœ:œAnthropicModelœ,œidœ:œAnthropicModel-5piN6œ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-StructuredOutput-ApbKx{œfieldNameœ:œllmœ,œidœ:œStructuredOutput-ApbKxœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", - "selected": false, - "source": "AnthropicModel-5piN6", - "sourceHandle": "{œdataTypeœ: œAnthropicModelœ, œidœ: œAnthropicModel-5piN6œ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", - "target": "StructuredOutput-ApbKx", - "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œStructuredOutput-ApbKxœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-sbo55", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "StructuredOutput-ApbKx", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-sbo55{œdataTypeœ:œParseDataœ,œidœ:œParseData-sbo55œ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-StructuredOutput-ApbKx{œfieldNameœ:œinput_valueœ,œidœ:œStructuredOutput-ApbKxœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-sbo55", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-sbo55œ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "StructuredOutput-ApbKx", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œStructuredOutput-ApbKxœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "File", - "id": "File-u0H8v", - "name": "data", - "output_types": [ - "Data" - ] - }, - "targetHandle": { - "fieldName": "data", - "id": "ParseData-sbo55", - "inputTypes": [ - "Data" - ], - "type": "other" - } - }, - "id": "reactflow__edge-File-u0H8v{œdataTypeœ:œFileœ,œidœ:œFile-u0H8vœ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-ParseData-sbo55{œfieldNameœ:œdataœ,œidœ:œParseData-sbo55œ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", - "selected": false, - "source": "File-u0H8v", - "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-u0H8vœ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-sbo55", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-sbo55œ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" + "source": "AnthropicModel-tZx4n", + "sourceHandle": "{œdataTypeœ: œAnthropicModelœ, œidœ: œAnthropicModel-tZx4nœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-iLekZ", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-iLekZœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -177,357 +150,62 @@ "data": { "sourceHandle": { "dataType": "StructuredOutput", - "id": "StructuredOutput-ApbKx", - "name": "structured_output", + "id": "StructuredOutput-tWLRa", + "name": "structured_output_dataframe", "output_types": [ - "Data" + "DataFrame" ] }, "targetHandle": { - "fieldName": "data", - "id": "ParseData-uKULv", + "fieldName": "input_data", + "id": "parser-ifKFs", "inputTypes": [ + "DataFrame", "Data" ], "type": "other" } }, - "id": "reactflow__edge-StructuredOutput-ApbKx{œdataTypeœ:œStructuredOutputœ,œidœ:œStructuredOutput-ApbKxœ,œnameœ:œstructured_outputœ,œoutput_typesœ:[œDataœ]}-ParseData-uKULv{œfieldNameœ:œdataœ,œidœ:œParseData-uKULvœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", + "id": "xy-edge__StructuredOutput-tWLRa{œdataTypeœ:œStructuredOutputœ,œidœ:œStructuredOutput-tWLRaœ,œnameœ:œstructured_output_dataframeœ,œoutput_typesœ:[œDataFrameœ]}-parser-ifKFs{œfieldNameœ:œinput_dataœ,œidœ:œparser-ifKFsœ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", "selected": false, - "source": "StructuredOutput-ApbKx", - "sourceHandle": "{œdataTypeœ: œStructuredOutputœ, œidœ: œStructuredOutput-ApbKxœ, œnameœ: œstructured_outputœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-uKULv", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-uKULvœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" + "source": "StructuredOutput-tWLRa", + "sourceHandle": "{œdataTypeœ: œStructuredOutputœ, œidœ: œStructuredOutput-tWLRaœ, œnameœ: œstructured_output_dataframeœ, œoutput_typesœ: [œDataFrameœ]}", + "target": "parser-ifKFs", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-ifKFsœ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-ifKFs", + "name": "parsed_text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "AnthropicModel-tZx4n", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "xy-edge__parser-ifKFs{œdataTypeœ:œparserœ,œidœ:œparser-ifKFsœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-AnthropicModel-tZx4n{œfieldNameœ:œinput_valueœ,œidœ:œAnthropicModel-tZx4nœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "parser-ifKFs", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-ifKFsœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "AnthropicModel-tZx4n", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAnthropicModel-tZx4nœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" } ], "nodes": [ { "data": { - "id": "ParseData-sbo55", - "node": { - "base_classes": [ - "Data", - "Message" - ], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert Data objects into Messages using any {field_name} from input data.", - "display_name": "Data to Message", - "documentation": "", - "edited": false, - "field_order": [ - "data", - "template", - "sep" - ], - "frozen": false, - "icon": "message-square", - "legacy": false, - "lf_version": "1.1.5", - "metadata": { - "legacy_name": "Parse Data" - }, - "minimized": false, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Message", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - }, - { - "allows_loop": false, - "cache": true, - "display_name": "Data List", - "method": "parse_data_as_list", - "name": "data_list", - "selected": "Data", - "tool_mode": true, - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" - }, - "data": { - "_input_type": "DataInput", - "advanced": false, - "display_name": "Data", - "dynamic": false, - "info": "The data to convert to text.", - "input_types": [ - "Data" - ], - "list": true, - "list_add_label": "Add More", - "name": "data", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "_input_type": "StrInput", - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "", - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "_input_type": "MultilineInput", - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template to use for formatting the data. It can contain the keys {text}, {data} or any other key in the Data.", - "input_types": [ - "Message" - ], - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "{text}" - } - }, - "tool_mode": false - }, - "showNode": true, - "type": "ParseData" - }, - "dragging": false, - "id": "ParseData-sbo55", - "measured": { - "height": 342, - "width": 320 - }, - "position": { - "x": 305.18655230615144, - "y": 482.32049719078225 - }, - "selected": false, - "type": "genericNode" - }, - { - "data": { - "id": "ParseData-uKULv", - "node": { - "base_classes": [ - "Data", - "Message" - ], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert Data objects into Messages using any {field_name} from input data.", - "display_name": "Data to Message", - "documentation": "", - "edited": false, - "field_order": [ - "data", - "template", - "sep" - ], - "frozen": false, - "icon": "message-square", - "legacy": false, - "lf_version": "1.1.5", - "metadata": { - "legacy_name": "Parse Data" - }, - "minimized": false, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Message", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - }, - { - "allows_loop": false, - "cache": true, - "display_name": "Data List", - "method": "parse_data_as_list", - "name": "data_list", - "selected": "Data", - "tool_mode": true, - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" - }, - "data": { - "_input_type": "DataInput", - "advanced": false, - "display_name": "Data", - "dynamic": false, - "info": "The data to convert to text.", - "input_types": [ - "Data" - ], - "list": true, - "list_add_label": "Add More", - "name": "data", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "_input_type": "StrInput", - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "", - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "_input_type": "MultilineInput", - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template to use for formatting the data. It can contain the keys {text}, {data} or any other key in the Data.", - "input_types": [ - "Message" - ], - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "{results}" - } - }, - "tool_mode": false - }, - "showNode": true, - "type": "ParseData" - }, - "dragging": false, - "id": "ParseData-uKULv", - "measured": { - "height": 342, - "width": 320 - }, - "position": { - "x": 1743.003626296405, - "y": 585.3047133010242 - }, - "selected": false, - "type": "genericNode" - }, - { - "data": { - "id": "TextInput-FRxv5", + "id": "TextInput-WR8cL", "node": { "base_classes": [ "Message" @@ -547,7 +225,7 @@ "icon": "type", "key": "TextInput", "legacy": false, - "lf_version": "1.1.5", + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -619,7 +297,7 @@ "type": "TextInput" }, "dragging": false, - "id": "TextInput-FRxv5", + "id": "TextInput-WR8cL", "measured": { "height": 230, "width": 320 @@ -633,7 +311,7 @@ }, { "data": { - "id": "AnthropicModel-5piN6", + "id": "AnthropicModel-fz6rd", "node": { "base_classes": [ "LanguageModel", @@ -663,7 +341,7 @@ "icon": "Anthropic", "key": "AnthropicModel", "legacy": false, - "lf_version": "1.1.5", + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -721,7 +399,7 @@ "show": true, "title_case": false, "type": "str", - "value": "ANTHROPIC_API_KEY" + "value": "" }, "base_url": { "_input_type": "MessageTextInput", @@ -955,7 +633,7 @@ "type": "AnthropicModel" }, "dragging": false, - "id": "AnthropicModel-5piN6", + "id": "AnthropicModel-fz6rd", "measured": { "height": 670, "width": 320 @@ -969,7 +647,7 @@ }, { "data": { - "id": "AnthropicModel-vog1V", + "id": "AnthropicModel-tZx4n", "node": { "base_classes": [ "LanguageModel", @@ -999,7 +677,7 @@ "icon": "Anthropic", "key": "AnthropicModel", "legacy": false, - "lf_version": "1.1.5", + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -1057,7 +735,7 @@ "show": true, "title_case": false, "type": "str", - "value": "ANTHROPIC_API_KEY" + "value": "" }, "base_url": { "_input_type": "MessageTextInput", @@ -1291,7 +969,7 @@ "type": "AnthropicModel" }, "dragging": false, - "id": "AnthropicModel-vog1V", + "id": "AnthropicModel-tZx4n", "measured": { "height": 670, "width": 320 @@ -1305,7 +983,7 @@ }, { "data": { - "id": "ChatOutput-vpJbx", + "id": "ChatOutput-iLekZ", "node": { "base_classes": [ "Message" @@ -1333,7 +1011,7 @@ "icon": "MessagesSquare", "key": "ChatOutput", "legacy": false, - "lf_version": "1.1.5", + "lf_version": "1.2.0", "metadata": {}, "minimized": true, "output_types": [], @@ -1603,7 +1281,7 @@ "type": "ChatOutput" }, "dragging": false, - "id": "ChatOutput-vpJbx", + "id": "ChatOutput-iLekZ", "measured": { "height": 66, "width": 192 @@ -1617,7 +1295,7 @@ }, { "data": { - "id": "note-KVOU7", + "id": "note-isxpR", "node": { "description": "### 💡 Upload your resume here", "display_name": "", @@ -1630,7 +1308,7 @@ }, "dragging": false, "height": 358, - "id": "note-KVOU7", + "id": "note-isxpR", "measured": { "height": 358, "width": 345 @@ -1646,7 +1324,7 @@ }, { "data": { - "id": "note-pq8w3", + "id": "note-zvgQE", "node": { "description": "## 📝 Portfolio Website Code Generator\n\nYour uploaded resume is parsed into a structured format, and output as HTML/CSS code for your own resume website!\n\n✅ **Accepted Formats:** PDF or TXT \n✅ To ensure readability, provide clear headings, bullet points, and proper formatting. \n### 📌 Structured output fields:\n1. 🏷 **Full Name** - Candidate's full name \n2. 📧 **Email** - A valid email address \n3. 📞 **Phone Number** - Contact number \n4. 🔗 **LinkedIn** - LinkedIn profile URL \n5. 🖥 **GitHub** - GitHub profile URL (if applicable) \n6. 🌐 **Portfolio** - Personal website or portfolio URL \n7. 🛂 **Visa Status** - Work authorization details (if applicable) \n8. 📝 **Summary** - A brief professional summary or objective statement \n9. 💼 **Experience** - Work experience details (in dictionary format) \n10. 🎓 **Education** - Education details (in dictionary format) \n11. 🛠 **Skills** - Skills mentioned in the resume (comma-separated) \n12. 🚀 **Projects** - Titles, descriptions, and details of projects.", "display_name": "", @@ -1657,7 +1335,7 @@ }, "dragging": false, "height": 324, - "id": "note-pq8w3", + "id": "note-zvgQE", "measured": { "height": 324, "width": 325 @@ -1673,7 +1351,7 @@ }, { "data": { - "id": "note-4GusB", + "id": "note-smoRV", "node": { "description": "### 💡 Click **Open table** to view the schema", "display_name": "", @@ -1686,7 +1364,7 @@ }, "dragging": false, "height": 438, - "id": "note-4GusB", + "id": "note-smoRV", "measured": { "height": 438, "width": 358 @@ -1702,7 +1380,7 @@ }, { "data": { - "id": "note-Tqu2d", + "id": "note-opd23", "node": { "description": "### 💡 Add your Anthropic API key here", "display_name": "", @@ -1715,7 +1393,7 @@ }, "dragging": false, "height": 324, - "id": "note-Tqu2d", + "id": "note-opd23", "measured": { "height": 324, "width": 361 @@ -1731,7 +1409,7 @@ }, { "data": { - "id": "note-Tc72L", + "id": "note-vBwkt", "node": { "description": "### 💡 Add your Anthropic API key here", "display_name": "", @@ -1744,7 +1422,7 @@ }, "dragging": false, "height": 324, - "id": "note-Tc72L", + "id": "note-vBwkt", "measured": { "height": 324, "width": 343 @@ -1760,7 +1438,7 @@ }, { "data": { - "id": "StructuredOutput-ApbKx", + "id": "StructuredOutput-tWLRa", "node": { "base_classes": [ "Data", @@ -1778,11 +1456,13 @@ "input_value", "system_prompt", "schema_name", - "output_schema" + "output_schema", + "multiple" ], "frozen": false, "icon": "braces", "legacy": false, + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -1923,7 +1603,7 @@ "hidden": false, "name": "name", "sortable": true, - "type": "text" + "type": "str" }, { "default": "description of field", @@ -1936,10 +1616,10 @@ "hidden": false, "name": "description", "sortable": true, - "type": "text" + "type": "str" }, { - "default": "text", + "default": "str", "description": "Indicate the data type of the output field (e.g., str, int, float, bool, list, dict).", "disable_edit": false, "display_name": "Type", @@ -1948,17 +1628,25 @@ "formatter": "text", "hidden": false, "name": "type", + "options": [ + "str", + "int", + "float", + "bool", + "list", + "dict" + ], "sortable": true, - "type": "text" + "type": "str" }, { - "default": "False", + "default": false, "description": "Set to True if this output field should be a list of the specified type.", "disable_edit": false, "display_name": "Multiple", "edit_mode": "inline", "filterable": true, - "formatter": "text", + "formatter": "boolean", "hidden": false, "name": "multiple", "sortable": true, @@ -2073,6 +1761,7 @@ "system_prompt": { "_input_type": "MultilineInput", "advanced": true, + "copy_field": false, "display_name": "Format Instructions", "dynamic": false, "info": "The instructions to the language model for formatting the output.", @@ -2101,7 +1790,7 @@ "type": "StructuredOutput" }, "dragging": false, - "id": "StructuredOutput-ApbKx", + "id": "StructuredOutput-tWLRa", "measured": { "height": 447, "width": 320 @@ -2115,7 +1804,7 @@ }, { "data": { - "id": "File-u0H8v", + "id": "File-v8ouW", "node": { "base_classes": [ "Data" @@ -2142,6 +1831,7 @@ "icon": "file-text", "key": "File", "legacy": false, + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -2409,7 +2099,7 @@ "type": "File" }, "dragging": false, - "id": "File-u0H8v", + "id": "File-v8ouW", "measured": { "height": 336, "width": 320 @@ -2420,17 +2110,367 @@ }, "selected": false, "type": "genericNode" + }, + { + "data": { + "id": "ParserComponent-wrPyP", + "node": { + "base_classes": [ + "Message" + ], + "beta": false, + "category": "processing", + "conditional_paths": [], + "custom_fields": {}, + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", + "documentation": "", + "edited": false, + "field_order": [ + "stringify", + "template", + "input_data", + "sep" + ], + "frozen": false, + "icon": "braces", + "key": "ParserComponent", + "legacy": false, + "lf_version": "1.2.0", + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", + "selected": "Message", + "tool_mode": true, + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 0.001, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" + }, + "input_data": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Data or DataFrame", + "dynamic": false, + "info": "Accepts either a DataFrame or a Data object.", + "input_types": [ + "DataFrame", + "Data" + ], + "list": false, + "list_add_label": "Add More", + "name": "input_data", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Parser" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "Text: {text}" + }, + "sep": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Separator", + "dynamic": false, + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "sep", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "\n" + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "ParserComponent" + }, + "dragging": false, + "id": "ParserComponent-wrPyP", + "measured": { + "height": 357, + "width": 320 + }, + "position": { + "x": 299.19957920557835, + "y": 511.92640315784786 + }, + "selected": false, + "type": "genericNode" + }, + { + "data": { + "id": "parser-ifKFs", + "node": { + "base_classes": [ + "Message" + ], + "beta": false, + "category": "processing", + "conditional_paths": [], + "custom_fields": {}, + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", + "documentation": "", + "edited": false, + "field_order": [ + "mode", + "pattern", + "input_data", + "sep" + ], + "frozen": false, + "icon": "braces", + "key": "parser", + "legacy": false, + "lf_version": "1.2.0", + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", + "selected": "Message", + "tool_mode": true, + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 2.220446049250313e-16, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n name = \"parser\"\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" + }, + "input_data": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Data or DataFrame", + "dynamic": false, + "info": "Accepts either a DataFrame or a Data object.", + "input_types": [ + "DataFrame", + "Data" + ], + "list": false, + "list_add_label": "Add More", + "name": "input_data", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Stringify" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": false, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "Text: {text}" + }, + "sep": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Separator", + "dynamic": false, + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "sep", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "\n" + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "parser" + }, + "dragging": false, + "id": "parser-ifKFs", + "measured": { + "height": 312, + "width": 320 + }, + "position": { + "x": 1739.3994366258964, + "y": 415.8221978438559 + }, + "selected": false, + "type": "genericNode" } ], "viewport": { - "x": 258.19631043779543, - "y": 250.36039957268596, - "zoom": 0.3767176834743995 + "x": 54.17007235163055, + "y": 267.40142033867886, + "zoom": 0.4655801942877969 } }, "description": "This template transforms PDF or TXT resume documents into structured JSON, generating a portfolio website HTML code from the structured data.", "endpoint_name": null, - "id": "c8719bf8-c53b-4d8d-a195-139891cad0f5", + "id": "7e497e5b-3b0f-4b11-9cd5-8662efad990b", "is_component": false, "last_tested_version": "1.2.0", "name": "Portfolio Website Code Generator", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json b/src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json index bf296b152..1a4872e4d 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json @@ -1,69 +1,13 @@ { "data": { "edges": [ - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "File", - "id": "File-Ktatn", - "name": "data", - "output_types": [ - "Data" - ] - }, - "targetHandle": { - "fieldName": "data", - "id": "ParseData-gouVC", - "inputTypes": [ - "Data" - ], - "type": "other" - } - }, - "id": "reactflow__edge-File-Ktatn{œdataTypeœ:œFileœ,œidœ:œFile-Ktatnœ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-ParseData-gouVC{œfieldNameœ:œdataœ,œidœ:œParseData-gouVCœ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", - "selected": false, - "source": "File-Ktatn", - "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-Ktatnœ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-gouVC", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-gouVCœ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-gouVC", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "text", - "id": "Prompt-epiSD", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-gouVC{œdataTypeœ:œParseDataœ,œidœ:œParseData-gouVCœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-Prompt-epiSD{œfieldNameœ:œtextœ,œidœ:œPrompt-epiSDœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-gouVC", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-gouVCœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-epiSD", - "targetHandle": "{œfieldNameœ: œtextœ, œidœ: œPrompt-epiSDœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "Prompt", - "id": "Prompt-epiSD", + "id": "Prompt-AJxY8", "name": "prompt", "output_types": [ "Message" @@ -71,19 +15,19 @@ }, "targetHandle": { "fieldName": "system_message", - "id": "OpenAIModel-ppS3O", + "id": "OpenAIModel-zVeWr", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-Prompt-epiSD{œdataTypeœ:œPromptœ,œidœ:œPrompt-epiSDœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-ppS3O{œfieldNameœ:œsystem_messageœ,œidœ:œOpenAIModel-ppS3Oœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-AJxY8{œdataTypeœ:œPromptœ,œidœ:œPrompt-AJxY8œ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-zVeWr{œfieldNameœ:œsystem_messageœ,œidœ:œOpenAIModel-zVeWrœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Prompt-epiSD", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-epiSDœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-ppS3O", - "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œOpenAIModel-ppS3Oœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "Prompt-AJxY8", + "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-AJxY8œ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-zVeWr", + "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œOpenAIModel-zVeWrœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -91,7 +35,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-ppS3O", + "id": "OpenAIModel-zVeWr", "name": "text_output", "output_types": [ "Message" @@ -99,19 +43,19 @@ }, "targetHandle": { "fieldName": "summary", - "id": "Prompt-l9XAo", + "id": "Prompt-nmNbi", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-OpenAIModel-ppS3O{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-ppS3Oœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-Prompt-l9XAo{œfieldNameœ:œsummaryœ,œidœ:œPrompt-l9XAoœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-OpenAIModel-zVeWr{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-zVeWrœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-Prompt-nmNbi{œfieldNameœ:œsummaryœ,œidœ:œPrompt-nmNbiœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "OpenAIModel-ppS3O", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-ppS3Oœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-l9XAo", - "targetHandle": "{œfieldNameœ: œsummaryœ, œidœ: œPrompt-l9XAoœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "OpenAIModel-zVeWr", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-zVeWrœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-nmNbi", + "targetHandle": "{œfieldNameœ: œsummaryœ, œidœ: œPrompt-nmNbiœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -119,7 +63,7 @@ "data": { "sourceHandle": { "dataType": "Prompt", - "id": "Prompt-l9XAo", + "id": "Prompt-nmNbi", "name": "prompt", "output_types": [ "Message" @@ -127,19 +71,19 @@ }, "targetHandle": { "fieldName": "system_message", - "id": "OpenAIModel-DxfrQ", + "id": "OpenAIModel-Izkdb", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-Prompt-l9XAo{œdataTypeœ:œPromptœ,œidœ:œPrompt-l9XAoœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-DxfrQ{œfieldNameœ:œsystem_messageœ,œidœ:œOpenAIModel-DxfrQœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-nmNbi{œdataTypeœ:œPromptœ,œidœ:œPrompt-nmNbiœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-Izkdb{œfieldNameœ:œsystem_messageœ,œidœ:œOpenAIModel-Izkdbœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Prompt-l9XAo", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-l9XAoœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-DxfrQ", - "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œOpenAIModel-DxfrQœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "Prompt-nmNbi", + "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-nmNbiœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-Izkdb", + "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œOpenAIModel-Izkdbœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -147,7 +91,7 @@ "data": { "sourceHandle": { "dataType": "Prompt", - "id": "Prompt-LKleN", + "id": "Prompt-LXvg7", "name": "prompt", "output_types": [ "Message" @@ -155,47 +99,19 @@ }, "targetHandle": { "fieldName": "system_message", - "id": "OpenAIModel-W1vhv", + "id": "OpenAIModel-Hl8vG", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-Prompt-LKleN{œdataTypeœ:œPromptœ,œidœ:œPrompt-LKleNœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-W1vhv{œfieldNameœ:œsystem_messageœ,œidœ:œOpenAIModel-W1vhvœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-LXvg7{œdataTypeœ:œPromptœ,œidœ:œPrompt-LXvg7œ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-Hl8vG{œfieldNameœ:œsystem_messageœ,œidœ:œOpenAIModel-Hl8vGœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Prompt-LKleN", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-LKleNœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-W1vhv", - "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œOpenAIModel-W1vhvœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-gouVC", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "input_value", - "id": "OpenAIModel-W1vhv", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-gouVC{œdataTypeœ:œParseDataœ,œidœ:œParseData-gouVCœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-W1vhv{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-W1vhvœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-gouVC", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-gouVCœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-W1vhv", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-W1vhvœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "Prompt-LXvg7", + "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-LXvg7œ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-Hl8vG", + "targetHandle": "{œfieldNameœ: œsystem_messageœ, œidœ: œOpenAIModel-Hl8vGœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -203,7 +119,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-W1vhv", + "id": "OpenAIModel-Hl8vG", "name": "text_output", "output_types": [ "Message" @@ -211,7 +127,7 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-V5ZFA", + "id": "ChatOutput-NS8z5", "inputTypes": [ "Data", "DataFrame", @@ -220,12 +136,12 @@ "type": "other" } }, - "id": "reactflow__edge-OpenAIModel-W1vhv{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-W1vhvœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-V5ZFA{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-V5ZFAœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-OpenAIModel-Hl8vG{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-Hl8vGœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-NS8z5{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-NS8z5œ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œotherœ}", "selected": false, - "source": "OpenAIModel-W1vhv", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-W1vhvœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-V5ZFA", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-V5ZFAœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œotherœ}" + "source": "OpenAIModel-Hl8vG", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-Hl8vGœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-NS8z5", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-NS8z5œ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -233,7 +149,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-DxfrQ", + "id": "OpenAIModel-Izkdb", "name": "text_output", "output_types": [ "Message" @@ -241,7 +157,7 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-8y94b", + "id": "ChatOutput-GzAXT", "inputTypes": [ "Data", "DataFrame", @@ -250,18 +166,74 @@ "type": "other" } }, - "id": "reactflow__edge-OpenAIModel-DxfrQ{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-DxfrQœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-8y94b{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-8y94bœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-OpenAIModel-Izkdb{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-Izkdbœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-GzAXT{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-GzAXTœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œotherœ}", "selected": false, - "source": "OpenAIModel-DxfrQ", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-DxfrQœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-8y94b", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-8y94bœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œotherœ}" + "source": "OpenAIModel-Izkdb", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-Izkdbœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-GzAXT", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-GzAXTœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "File", + "id": "File-m5GWE", + "name": "message", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "input_value", + "id": "OpenAIModel-Hl8vG", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "xy-edge__File-m5GWE{œdataTypeœ:œFileœ,œidœ:œFile-m5GWEœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-Hl8vG{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-Hl8vGœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "File-m5GWE", + "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-m5GWEœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-Hl8vG", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-Hl8vGœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + }, + { + "animated": false, + "className": "", + "data": { + "sourceHandle": { + "dataType": "File", + "id": "File-m5GWE", + "name": "message", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "text", + "id": "Prompt-AJxY8", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "xy-edge__File-m5GWE{œdataTypeœ:œFileœ,œidœ:œFile-m5GWEœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Prompt-AJxY8{œfieldNameœ:œtextœ,œidœ:œPrompt-AJxY8œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "File-m5GWE", + "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-m5GWEœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-AJxY8", + "targetHandle": "{œfieldNameœ: œtextœ, œidœ: œPrompt-AJxY8œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" } ], "nodes": [ { "data": { - "id": "File-Ktatn", + "id": "File-m5GWE", "node": { "base_classes": [ "Data" @@ -481,7 +453,7 @@ "bz2", "gz" ], - "file_path": "43bb2a52-8dbf-4edf-a200-c54ee0e7fa1f\\2025-02-21_09-35-24_messages.json", + "file_path": [], "info": "Supported file extensions: txt, md, mdx, csv, json, yaml, yml, xml, html, htm, pdf, docx, py, sh, sql, js, ts, tsx; optionally bundled in file extensions: zip, tar, tgz, bz2, gz", "list": true, "list_add_label": "Add More", @@ -556,183 +528,21 @@ "type": "File" }, "dragging": false, - "id": "File-Ktatn", + "id": "File-m5GWE", "measured": { - "height": 228, + "height": 336, "width": 320 }, "position": { - "x": -2423.1133566137846, - "y": 736.6681755311793 + "x": -2283.1962393600293, + "y": 660.3497479382216 }, "selected": false, "type": "genericNode" }, { "data": { - "id": "ParseData-gouVC", - "node": { - "base_classes": [ - "Data", - "Message" - ], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert Data objects into Messages using any {field_name} from input data.", - "display_name": "Data to Message", - "documentation": "", - "edited": false, - "field_order": [ - "data", - "template", - "sep" - ], - "frozen": false, - "icon": "message-square", - "legacy": false, - "lf_version": "1.2.0", - "metadata": { - "legacy_name": "Parse Data" - }, - "minimized": false, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Message", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - }, - { - "allows_loop": false, - "cache": true, - "display_name": "Data List", - "method": "parse_data_as_list", - "name": "data_list", - "selected": "Data", - "tool_mode": true, - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" - }, - "data": { - "_input_type": "DataInput", - "advanced": false, - "display_name": "Data", - "dynamic": false, - "info": "The data to convert to text.", - "input_types": [ - "Data" - ], - "list": true, - "list_add_label": "Add More", - "name": "data", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "_input_type": "StrInput", - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "", - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "_input_type": "MultilineInput", - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template to use for formatting the data. It can contain the keys {text}, {data} or any other key in the Data.", - "input_types": [ - "Message" - ], - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "list of messages details: {file_path}" - } - }, - "tool_mode": false - }, - "showNode": true, - "type": "ParseData" - }, - "dragging": false, - "id": "ParseData-gouVC", - "measured": { - "height": 342, - "width": 320 - }, - "position": { - "x": -2048.092643605176, - "y": 650.2904629519279 - }, - "selected": false, - "type": "genericNode" - }, - { - "data": { - "id": "Prompt-l9XAo", + "id": "Prompt-nmNbi", "node": { "base_classes": [ "Message" @@ -871,9 +681,9 @@ "type": "Prompt" }, "dragging": false, - "id": "Prompt-l9XAo", + "id": "Prompt-nmNbi", "measured": { - "height": 339, + "height": 413, "width": 320 }, "position": { @@ -885,7 +695,7 @@ }, { "data": { - "id": "Prompt-epiSD", + "id": "Prompt-AJxY8", "node": { "base_classes": [ "Message" @@ -1024,9 +834,9 @@ "type": "Prompt" }, "dragging": false, - "id": "Prompt-epiSD", + "id": "Prompt-AJxY8", "measured": { - "height": 339, + "height": 413, "width": 320 }, "position": { @@ -1038,7 +848,7 @@ }, { "data": { - "id": "OpenAIModel-ppS3O", + "id": "OpenAIModel-zVeWr", "node": { "base_classes": [ "LanguageModel", @@ -1117,7 +927,7 @@ "input_types": [ "Message" ], - "load_from_db": false, + "load_from_db": true, "name": "api_key", "password": true, "placeholder": "", @@ -1406,9 +1216,9 @@ "type": "OpenAIModel" }, "dragging": false, - "id": "OpenAIModel-ppS3O", + "id": "OpenAIModel-zVeWr", "measured": { - "height": 656, + "height": 525, "width": 320 }, "position": { @@ -1420,7 +1230,7 @@ }, { "data": { - "id": "OpenAIModel-DxfrQ", + "id": "OpenAIModel-Izkdb", "node": { "base_classes": [ "LanguageModel", @@ -1499,7 +1309,7 @@ "input_types": [ "Message" ], - "load_from_db": false, + "load_from_db": true, "name": "api_key", "password": true, "placeholder": "", @@ -1788,9 +1598,9 @@ "type": "OpenAIModel" }, "dragging": false, - "id": "OpenAIModel-DxfrQ", + "id": "OpenAIModel-Izkdb", "measured": { - "height": 656, + "height": 525, "width": 320 }, "position": { @@ -1802,7 +1612,7 @@ }, { "data": { - "id": "Prompt-LKleN", + "id": "Prompt-LXvg7", "node": { "base_classes": [ "Message" @@ -1917,9 +1727,9 @@ "type": "Prompt" }, "dragging": false, - "id": "Prompt-LKleN", + "id": "Prompt-LXvg7", "measured": { - "height": 256, + "height": 330, "width": 320 }, "position": { @@ -1931,7 +1741,7 @@ }, { "data": { - "id": "OpenAIModel-W1vhv", + "id": "OpenAIModel-Hl8vG", "node": { "base_classes": [ "LanguageModel", @@ -2010,7 +1820,7 @@ "input_types": [ "Message" ], - "load_from_db": false, + "load_from_db": true, "name": "api_key", "password": true, "placeholder": "", @@ -2299,9 +2109,9 @@ "type": "OpenAIModel" }, "dragging": false, - "id": "OpenAIModel-W1vhv", + "id": "OpenAIModel-Hl8vG", "measured": { - "height": 656, + "height": 525, "width": 320 }, "position": { @@ -2313,7 +2123,7 @@ }, { "data": { - "id": "note-oqDGB", + "id": "note-D3g3A", "node": { "description": "# Sentiment Analysis Flow \n\nThis flow processes text data, analyzes sentiment, and provides structured insights. \n\n## Prerequisite\n\n* [OpenAI API key](https://platform.openai.com/docs/)\n\n## Quickstart\n\n1. Add your [OpenAI API key](https://platform.openai.com/docs/) to the OpenAI model components.\n2. In the **File Component**, load text data in `.txt`, `.csv`, or `.json` formats.\n3. Open the **Playground** to see the analysis and recommendation the flow constructs.\n\n## How It Works \n\n1. The **Data to Message** component converts raw data into structured messages. \n\n2. The **NLP expert** prompt provides sentiment analysis, while the **Analyzing messages** prompt summarizes messages from a discussion board.\n\n3. The final **Prompt Component** creates a structured recommendation prompt to ensure that the AI model receives well-formatted input. \n\n4. The **OpenAI Model Component** processes the text and classifies the sentiment as **Positive, Neutral, or Negative**. \n\n", "display_name": "", @@ -2324,7 +2134,7 @@ }, "dragging": false, "height": 574, - "id": "note-oqDGB", + "id": "note-D3g3A", "measured": { "height": 574, "width": 413 @@ -2340,7 +2150,7 @@ }, { "data": { - "id": "ChatOutput-V5ZFA", + "id": "ChatOutput-NS8z5", "node": { "base_classes": [ "Message" @@ -2633,7 +2443,7 @@ "type": "ChatOutput" }, "dragging": false, - "id": "ChatOutput-V5ZFA", + "id": "ChatOutput-NS8z5", "measured": { "height": 192, "width": 320 @@ -2647,7 +2457,7 @@ }, { "data": { - "id": "ChatOutput-8y94b", + "id": "ChatOutput-GzAXT", "node": { "base_classes": [ "Message" @@ -2940,7 +2750,7 @@ "type": "ChatOutput" }, "dragging": false, - "id": "ChatOutput-8y94b", + "id": "ChatOutput-GzAXT", "measured": { "height": 192, "width": 320 @@ -2954,7 +2764,7 @@ }, { "data": { - "id": "note-fOJpn", + "id": "note-Sg6zZ", "node": { "description": "### 💡 Add your OpenAI API key here 👇", "display_name": "", @@ -2967,7 +2777,7 @@ }, "dragging": false, "height": 326, - "id": "note-fOJpn", + "id": "note-Sg6zZ", "measured": { "height": 326, "width": 352 @@ -2983,7 +2793,7 @@ }, { "data": { - "id": "note-PJ0gY", + "id": "note-oCG60", "node": { "description": "### 💡 Add your OpenAI API key here 👇", "display_name": "", @@ -2995,7 +2805,7 @@ "type": "note" }, "dragging": false, - "id": "note-PJ0gY", + "id": "note-oCG60", "measured": { "height": 324, "width": 324 @@ -3009,7 +2819,7 @@ }, { "data": { - "id": "note-yzNaN", + "id": "note-hEufz", "node": { "description": "### 💡 Add your OpenAI API key here 👇", "display_name": "", @@ -3021,7 +2831,7 @@ "type": "note" }, "dragging": false, - "id": "note-yzNaN", + "id": "note-hEufz", "measured": { "height": 324, "width": 324 @@ -3030,19 +2840,19 @@ "x": -1309.8036340068625, "y": 925.6888138443481 }, - "selected": true, + "selected": false, "type": "noteNode" } ], "viewport": { - "x": 1436.086487750284, - "y": 17.453112924488266, - "zoom": 0.48563499996133874 + "x": 1195.5900912340421, + "y": 170.90395042473165, + "zoom": 0.5503258036709812 } }, "description": "Load text data from various file formats, process it into structured messages, and analyze sentiment using AI-powered classification.", "endpoint_name": null, - "id": "4d068861-cb44-46b0-a70f-15467baab096", + "id": "ee875a1c-3b8a-4500-8a6b-bb5d1534b5de", "is_component": false, "last_tested_version": "1.2.0", "name": "Text Sentiment Analysis", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json b/src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json index 246200b76..93d246671 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json @@ -1,42 +1,13 @@ { "data": { "edges": [ - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseData", - "id": "ParseData-Pc764", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "context", - "id": "Prompt-T1JLQ", - "inputTypes": [ - "Message", - "Text" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseData-Pc764{œdataTypeœ:œParseDataœ,œidœ:œParseData-Pc764œ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-Prompt-T1JLQ{œfieldNameœ:œcontextœ,œidœ:œPrompt-T1JLQœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseData-Pc764", - "sourceHandle": "{œdataTypeœ: œParseDataœ, œidœ: œParseData-Pc764œ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-T1JLQ", - "targetHandle": "{œfieldNameœ: œcontextœ, œidœ: œPrompt-T1JLQœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" - }, { "animated": false, "className": "", "data": { "sourceHandle": { "dataType": "ChatInput", - "id": "ChatInput-5reba", + "id": "ChatInput-GPa5O", "name": "message", "output_types": [ "Message" @@ -44,7 +15,7 @@ }, "targetHandle": { "fieldName": "question", - "id": "Prompt-T1JLQ", + "id": "Prompt-NEGIF", "inputTypes": [ "Message", "Text" @@ -52,12 +23,12 @@ "type": "str" } }, - "id": "reactflow__edge-ChatInput-5reba{œdataTypeœ:œChatInputœ,œidœ:œChatInput-5rebaœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Prompt-T1JLQ{œfieldNameœ:œquestionœ,œidœ:œPrompt-T1JLQœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-GPa5O{œdataTypeœ:œChatInputœ,œidœ:œChatInput-GPa5Oœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Prompt-NEGIF{œfieldNameœ:œquestionœ,œidœ:œPrompt-NEGIFœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", "selected": false, - "source": "ChatInput-5reba", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-5rebaœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-T1JLQ", - "targetHandle": "{œfieldNameœ: œquestionœ, œidœ: œPrompt-T1JLQœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" + "source": "ChatInput-GPa5O", + "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-GPa5Oœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-NEGIF", + "targetHandle": "{œfieldNameœ: œquestionœ, œidœ: œPrompt-NEGIFœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -65,7 +36,7 @@ "data": { "sourceHandle": { "dataType": "File", - "id": "File-IwyQk", + "id": "File-acgDn", "name": "data", "output_types": [ "Data" @@ -73,7 +44,7 @@ }, "targetHandle": { "fieldName": "data_inputs", - "id": "SplitText-EixdW", + "id": "SplitText-PK3Bw", "inputTypes": [ "Data", "DataFrame" @@ -81,12 +52,12 @@ "type": "other" } }, - "id": "reactflow__edge-File-IwyQk{œdataTypeœ:œFileœ,œidœ:œFile-IwyQkœ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-SplitText-EixdW{œfieldNameœ:œdata_inputsœ,œidœ:œSplitText-EixdWœ,œinputTypesœ:[œDataœ,œDataFrameœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-File-acgDn{œdataTypeœ:œFileœ,œidœ:œFile-acgDnœ,œnameœ:œdataœ,œoutput_typesœ:[œDataœ]}-SplitText-PK3Bw{œfieldNameœ:œdata_inputsœ,œidœ:œSplitText-PK3Bwœ,œinputTypesœ:[œDataœ,œDataFrameœ],œtypeœ:œotherœ}", "selected": false, - "source": "File-IwyQk", - "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-IwyQkœ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", - "target": "SplitText-EixdW", - "targetHandle": "{œfieldNameœ: œdata_inputsœ, œidœ: œSplitText-EixdWœ, œinputTypesœ: [œDataœ, œDataFrameœ], œtypeœ: œotherœ}" + "source": "File-acgDn", + "sourceHandle": "{œdataTypeœ: œFileœ, œidœ: œFile-acgDnœ, œnameœ: œdataœ, œoutput_typesœ: [œDataœ]}", + "target": "SplitText-PK3Bw", + "targetHandle": "{œfieldNameœ: œdata_inputsœ, œidœ: œSplitText-PK3Bwœ, œinputTypesœ: [œDataœ, œDataFrameœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -94,7 +65,7 @@ "data": { "sourceHandle": { "dataType": "Prompt", - "id": "Prompt-T1JLQ", + "id": "Prompt-NEGIF", "name": "prompt", "output_types": [ "Message" @@ -102,19 +73,19 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "OpenAIModel-e49kI", + "id": "OpenAIModel-smg8l", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-Prompt-T1JLQ{œdataTypeœ:œPromptœ,œidœ:œPrompt-T1JLQœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-e49kI{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-e49kIœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-NEGIF{œdataTypeœ:œPromptœ,œidœ:œPrompt-NEGIFœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-OpenAIModel-smg8l{œfieldNameœ:œinput_valueœ,œidœ:œOpenAIModel-smg8lœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Prompt-T1JLQ", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-T1JLQœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "OpenAIModel-e49kI", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-e49kIœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "Prompt-NEGIF", + "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-NEGIFœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", + "target": "OpenAIModel-smg8l", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œOpenAIModel-smg8lœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -122,7 +93,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-e49kI", + "id": "OpenAIModel-smg8l", "name": "text_output", "output_types": [ "Message" @@ -130,7 +101,7 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-aQXd2", + "id": "ChatOutput-71awB", "inputTypes": [ "Data", "DataFrame", @@ -139,12 +110,12 @@ "type": "str" } }, - "id": "reactflow__edge-OpenAIModel-e49kI{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-e49kIœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-aQXd2{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-aQXd2œ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-OpenAIModel-smg8l{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-smg8lœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-71awB{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-71awBœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "OpenAIModel-e49kI", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-e49kIœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-aQXd2", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-aQXd2œ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" + "source": "OpenAIModel-smg8l", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-smg8lœ, œnameœ: œtext_outputœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-71awB", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-71awBœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -152,7 +123,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIEmbeddings", - "id": "OpenAIEmbeddings-fftff", + "id": "OpenAIEmbeddings-wJbwl", "name": "embeddings", "output_types": [ "Embeddings" @@ -160,19 +131,19 @@ }, "targetHandle": { "fieldName": "embedding_model", - "id": "AstraDB-JF2lS", + "id": "AstraDB-QiWTk", "inputTypes": [ "Embeddings" ], "type": "other" } }, - "id": "reactflow__edge-OpenAIEmbeddings-fftff{œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-fftffœ,œnameœ:œembeddingsœ,œoutput_typesœ:[œEmbeddingsœ]}-AstraDB-JF2lS{œfieldNameœ:œembedding_modelœ,œidœ:œAstraDB-JF2lSœ,œinputTypesœ:[œEmbeddingsœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-OpenAIEmbeddings-wJbwl{œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-wJbwlœ,œnameœ:œembeddingsœ,œoutput_typesœ:[œEmbeddingsœ]}-AstraDB-QiWTk{œfieldNameœ:œembedding_modelœ,œidœ:œAstraDB-QiWTkœ,œinputTypesœ:[œEmbeddingsœ],œtypeœ:œotherœ}", "selected": false, - "source": "OpenAIEmbeddings-fftff", - "sourceHandle": "{œdataTypeœ: œOpenAIEmbeddingsœ, œidœ: œOpenAIEmbeddings-fftffœ, œnameœ: œembeddingsœ, œoutput_typesœ: [œEmbeddingsœ]}", - "target": "AstraDB-JF2lS", - "targetHandle": "{œfieldNameœ: œembedding_modelœ, œidœ: œAstraDB-JF2lSœ, œinputTypesœ: [œEmbeddingsœ], œtypeœ: œotherœ}" + "source": "OpenAIEmbeddings-wJbwl", + "sourceHandle": "{œdataTypeœ: œOpenAIEmbeddingsœ, œidœ: œOpenAIEmbeddings-wJbwlœ, œnameœ: œembeddingsœ, œoutput_typesœ: [œEmbeddingsœ]}", + "target": "AstraDB-QiWTk", + "targetHandle": "{œfieldNameœ: œembedding_modelœ, œidœ: œAstraDB-QiWTkœ, œinputTypesœ: [œEmbeddingsœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -180,7 +151,7 @@ "data": { "sourceHandle": { "dataType": "SplitText", - "id": "SplitText-EixdW", + "id": "SplitText-PK3Bw", "name": "chunks", "output_types": [ "Data" @@ -188,7 +159,7 @@ }, "targetHandle": { "fieldName": "ingest_data", - "id": "AstraDB-JF2lS", + "id": "AstraDB-QiWTk", "inputTypes": [ "Data", "DataFrame" @@ -196,12 +167,12 @@ "type": "other" } }, - "id": "reactflow__edge-SplitText-EixdW{œdataTypeœ:œSplitTextœ,œidœ:œSplitText-EixdWœ,œnameœ:œchunksœ,œoutput_typesœ:[œDataœ]}-AstraDB-JF2lS{œfieldNameœ:œingest_dataœ,œidœ:œAstraDB-JF2lSœ,œinputTypesœ:[œDataœ,œDataFrameœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-SplitText-PK3Bw{œdataTypeœ:œSplitTextœ,œidœ:œSplitText-PK3Bwœ,œnameœ:œchunksœ,œoutput_typesœ:[œDataœ]}-AstraDB-QiWTk{œfieldNameœ:œingest_dataœ,œidœ:œAstraDB-QiWTkœ,œinputTypesœ:[œDataœ,œDataFrameœ],œtypeœ:œotherœ}", "selected": false, - "source": "SplitText-EixdW", - "sourceHandle": "{œdataTypeœ: œSplitTextœ, œidœ: œSplitText-EixdWœ, œnameœ: œchunksœ, œoutput_typesœ: [œDataœ]}", - "target": "AstraDB-JF2lS", - "targetHandle": "{œfieldNameœ: œingest_dataœ, œidœ: œAstraDB-JF2lSœ, œinputTypesœ: [œDataœ, œDataFrameœ], œtypeœ: œotherœ}" + "source": "SplitText-PK3Bw", + "sourceHandle": "{œdataTypeœ: œSplitTextœ, œidœ: œSplitText-PK3Bwœ, œnameœ: œchunksœ, œoutput_typesœ: [œDataœ]}", + "target": "AstraDB-QiWTk", + "targetHandle": "{œfieldNameœ: œingest_dataœ, œidœ: œAstraDB-QiWTkœ, œinputTypesœ: [œDataœ, œDataFrameœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -209,7 +180,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIEmbeddings", - "id": "OpenAIEmbeddings-t4aMI", + "id": "OpenAIEmbeddings-hOLGN", "name": "embeddings", "output_types": [ "Embeddings" @@ -217,19 +188,19 @@ }, "targetHandle": { "fieldName": "embedding_model", - "id": "AstraDB-8CuoQ", + "id": "AstraDB-MxkZ3", "inputTypes": [ "Embeddings" ], "type": "other" } }, - "id": "reactflow__edge-OpenAIEmbeddings-t4aMI{œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-t4aMIœ,œnameœ:œembeddingsœ,œoutput_typesœ:[œEmbeddingsœ]}-AstraDB-8CuoQ{œfieldNameœ:œembedding_modelœ,œidœ:œAstraDB-8CuoQœ,œinputTypesœ:[œEmbeddingsœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-OpenAIEmbeddings-hOLGN{œdataTypeœ:œOpenAIEmbeddingsœ,œidœ:œOpenAIEmbeddings-hOLGNœ,œnameœ:œembeddingsœ,œoutput_typesœ:[œEmbeddingsœ]}-AstraDB-MxkZ3{œfieldNameœ:œembedding_modelœ,œidœ:œAstraDB-MxkZ3œ,œinputTypesœ:[œEmbeddingsœ],œtypeœ:œotherœ}", "selected": false, - "source": "OpenAIEmbeddings-t4aMI", - "sourceHandle": "{œdataTypeœ: œOpenAIEmbeddingsœ, œidœ: œOpenAIEmbeddings-t4aMIœ, œnameœ: œembeddingsœ, œoutput_typesœ: [œEmbeddingsœ]}", - "target": "AstraDB-8CuoQ", - "targetHandle": "{œfieldNameœ: œembedding_modelœ, œidœ: œAstraDB-8CuoQœ, œinputTypesœ: [œEmbeddingsœ], œtypeœ: œotherœ}" + "source": "OpenAIEmbeddings-hOLGN", + "sourceHandle": "{œdataTypeœ: œOpenAIEmbeddingsœ, œidœ: œOpenAIEmbeddings-hOLGNœ, œnameœ: œembeddingsœ, œoutput_typesœ: [œEmbeddingsœ]}", + "target": "AstraDB-MxkZ3", + "targetHandle": "{œfieldNameœ: œembedding_modelœ, œidœ: œAstraDB-MxkZ3œ, œinputTypesœ: [œEmbeddingsœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -237,7 +208,7 @@ "data": { "sourceHandle": { "dataType": "ChatInput", - "id": "ChatInput-5reba", + "id": "ChatInput-GPa5O", "name": "message", "output_types": [ "Message" @@ -245,47 +216,71 @@ }, "targetHandle": { "fieldName": "search_query", - "id": "AstraDB-8CuoQ", + "id": "AstraDB-MxkZ3", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-ChatInput-5reba{œdataTypeœ:œChatInputœ,œidœ:œChatInput-5rebaœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-AstraDB-8CuoQ{œfieldNameœ:œsearch_queryœ,œidœ:œAstraDB-8CuoQœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-GPa5O{œdataTypeœ:œChatInputœ,œidœ:œChatInput-GPa5Oœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-AstraDB-MxkZ3{œfieldNameœ:œsearch_queryœ,œidœ:œAstraDB-MxkZ3œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "ChatInput-5reba", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-5rebaœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "AstraDB-8CuoQ", - "targetHandle": "{œfieldNameœ: œsearch_queryœ, œidœ: œAstraDB-8CuoQœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "ChatInput-GPa5O", + "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-GPa5Oœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "AstraDB-MxkZ3", + "targetHandle": "{œfieldNameœ: œsearch_queryœ, œidœ: œAstraDB-MxkZ3œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { - "animated": false, - "className": "", "data": { "sourceHandle": { "dataType": "AstraDB", - "id": "AstraDB-8CuoQ", - "name": "search_results", + "id": "AstraDB-MxkZ3", + "name": "dataframe", "output_types": [ - "Data" + "DataFrame" ] }, "targetHandle": { - "fieldName": "data", - "id": "ParseData-Pc764", + "fieldName": "input_data", + "id": "parser-UZXIp", "inputTypes": [ + "DataFrame", "Data" ], "type": "other" } }, - "id": "reactflow__edge-AstraDB-8CuoQ{œdataTypeœ:œAstraDBœ,œidœ:œAstraDB-8CuoQœ,œnameœ:œsearch_resultsœ,œoutput_typesœ:[œDataœ]}-ParseData-Pc764{œfieldNameœ:œdataœ,œidœ:œParseData-Pc764œ,œinputTypesœ:[œDataœ],œtypeœ:œotherœ}", - "selected": false, - "source": "AstraDB-8CuoQ", - "sourceHandle": "{œdataTypeœ: œAstraDBœ, œidœ: œAstraDB-8CuoQœ, œnameœ: œsearch_resultsœ, œoutput_typesœ: [œDataœ]}", - "target": "ParseData-Pc764", - "targetHandle": "{œfieldNameœ: œdataœ, œidœ: œParseData-Pc764œ, œinputTypesœ: [œDataœ], œtypeœ: œotherœ}" + "id": "xy-edge__AstraDB-MxkZ3{œdataTypeœ:œAstraDBœ,œidœ:œAstraDB-MxkZ3œ,œnameœ:œdataframeœ,œoutput_typesœ:[œDataFrameœ]}-parser-UZXIp{œfieldNameœ:œinput_dataœ,œidœ:œparser-UZXIpœ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", + "source": "AstraDB-MxkZ3", + "sourceHandle": "{œdataTypeœ: œAstraDBœ, œidœ: œAstraDB-MxkZ3œ, œnameœ: œdataframeœ, œoutput_typesœ: [œDataFrameœ]}", + "target": "parser-UZXIp", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-UZXIpœ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" + }, + { + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-UZXIp", + "name": "parsed_text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "context", + "id": "Prompt-NEGIF", + "inputTypes": [ + "Message", + "Text" + ], + "type": "str" + } + }, + "id": "xy-edge__parser-UZXIp{œdataTypeœ:œparserœ,œidœ:œparser-UZXIpœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-Prompt-NEGIF{œfieldNameœ:œcontextœ,œidœ:œPrompt-NEGIFœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}", + "source": "parser-UZXIp", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-UZXIpœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-NEGIF", + "targetHandle": "{œfieldNameœ: œcontextœ, œidœ: œPrompt-NEGIFœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}" } ], "nodes": [ @@ -293,7 +288,7 @@ "data": { "description": "Get chat inputs from the Playground.", "display_name": "Chat Input", - "id": "ChatInput-5reba", + "id": "ChatInput-GPa5O", "node": { "base_classes": [ "Message" @@ -316,7 +311,7 @@ "frozen": false, "icon": "MessagesSquare", "legacy": false, - "lf_version": "1.1.1", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -558,7 +553,7 @@ }, "dragging": false, "height": 234, - "id": "ChatInput-5reba", + "id": "ChatInput-GPa5O", "measured": { "height": 234, "width": 320 @@ -575,168 +570,11 @@ "type": "genericNode", "width": 320 }, - { - "data": { - "description": "Convert Data into plain text following a specified template.", - "display_name": "Parse Data", - "id": "ParseData-Pc764", - "node": { - "base_classes": [ - "Message" - ], - "beta": false, - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert Data into plain text following a specified template.", - "display_name": "Parse Data", - "documentation": "", - "edited": false, - "field_order": [ - "data", - "template", - "sep" - ], - "frozen": false, - "icon": "message-square", - "legacy": false, - "lf_version": "1.1.1", - "metadata": { - "legacy_name": "Parse Data" - }, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Message", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - }, - { - "allows_loop": false, - "cache": true, - "display_name": "Data List", - "method": "parse_data_as_list", - "name": "data_list", - "selected": "Data", - "tool_mode": true, - "types": [ - "Data" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.helpers.data import data_to_text, data_to_text_list\nfrom langflow.io import DataInput, MultilineInput, Output, StrInput\nfrom langflow.schema import Data\nfrom langflow.schema.message import Message\n\n\nclass ParseDataComponent(Component):\n display_name = \"Data to Message\"\n description = \"Convert Data objects into Messages using any {field_name} from input data.\"\n icon = \"message-square\"\n name = \"ParseData\"\n metadata = {\n \"legacy_name\": \"Parse Data\",\n }\n\n inputs = [\n DataInput(\n name=\"data\",\n display_name=\"Data\",\n info=\"The data to convert to text.\",\n is_list=True,\n required=True,\n ),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=\"The template to use for formatting the data. \"\n \"It can contain the keys {text}, {data} or any other key in the Data.\",\n value=\"{text}\",\n required=True,\n ),\n StrInput(name=\"sep\", display_name=\"Separator\", advanced=True, value=\"\\n\"),\n ]\n\n outputs = [\n Output(\n display_name=\"Message\",\n name=\"text\",\n info=\"Data as a single Message, with each input Data separated by Separator\",\n method=\"parse_data\",\n ),\n Output(\n display_name=\"Data List\",\n name=\"data_list\",\n info=\"Data as a list of new Data, each having `text` formatted by Template\",\n method=\"parse_data_as_list\",\n ),\n ]\n\n def _clean_args(self) -> tuple[list[Data], str, str]:\n data = self.data if isinstance(self.data, list) else [self.data]\n template = self.template\n sep = self.sep\n return data, template, sep\n\n def parse_data(self) -> Message:\n data, template, sep = self._clean_args()\n result_string = data_to_text(template, data, sep)\n self.status = result_string\n return Message(text=result_string)\n\n def parse_data_as_list(self) -> list[Data]:\n data, template, _ = self._clean_args()\n text_list, data_list = data_to_text_list(template, data)\n for item, text in zip(data_list, text_list, strict=True):\n item.set_text(text)\n self.status = data_list\n return data_list\n" - }, - "data": { - "advanced": false, - "display_name": "Data", - "dynamic": false, - "info": "The data to convert to text.", - "input_types": [ - "Data" - ], - "list": true, - "name": "data", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "", - "list": false, - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template to use for formatting the data. It can contain the keys {text}, {data} or any other key in the Data.", - "input_types": [ - "Message" - ], - "list": false, - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "{text}" - } - } - }, - "type": "ParseData" - }, - "dragging": false, - "height": 350, - "id": "ParseData-Pc764", - "measured": { - "height": 350, - "width": 320 - }, - "position": { - "x": 1606.0595305373527, - "y": 751.4473696960695 - }, - "positionAbsolute": { - "x": 1606.0595305373527, - "y": 751.4473696960695 - }, - "selected": false, - "type": "genericNode", - "width": 320 - }, { "data": { "description": "Create a prompt template with dynamic variables.", "display_name": "Prompt", - "id": "Prompt-T1JLQ", + "id": "Prompt-NEGIF", "node": { "base_classes": [ "Message" @@ -895,7 +733,7 @@ }, "dragging": false, "height": 433, - "id": "Prompt-T1JLQ", + "id": "Prompt-NEGIF", "measured": { "height": 433, "width": 320 @@ -916,7 +754,7 @@ "data": { "description": "Split text into chunks based on specified criteria.", "display_name": "Split Text", - "id": "SplitText-EixdW", + "id": "SplitText-PK3Bw", "node": { "base_classes": [ "Data" @@ -1112,7 +950,7 @@ }, "dragging": false, "height": 475, - "id": "SplitText-EixdW", + "id": "SplitText-PK3Bw", "measured": { "height": 475, "width": 320 @@ -1131,7 +969,7 @@ }, { "data": { - "id": "note-En1Ka", + "id": "note-cMJub", "node": { "description": "## 🐕 2. Retriever Flow\n\nThis flow answers your questions with contextual data retrieved from your vector database.\n\nOpen the **Playground** and ask, \n\n```\nWhat is this document about?\n```\n", "display_name": "", @@ -1144,7 +982,7 @@ }, "dragging": false, "height": 324, - "id": "note-En1Ka", + "id": "note-cMJub", "measured": { "height": 324, "width": 325 @@ -1168,7 +1006,7 @@ }, { "data": { - "id": "note-SHxvt", + "id": "note-Jv9dw", "node": { "description": "## 📖 README\n\nLoad your data into a vector database with the 📚 **Load Data** flow, and then use your data as chat context with the 🐕 **Retriever** flow.\n\n**🚨 Add your OpenAI API key as a global variable to easily add it to all of the OpenAI components in this flow.** \n\n**Quick start**\n1. Run the 📚 **Load Data** flow.\n2. Run the 🐕 **Retriever** flow.\n\n**Next steps** \n\n- Experiment by changing the prompt and the loaded data to see how the bot's responses change. \n\nFor more info, see the [Langflow docs](https://docs.langflow.org/starter-projects-vector-store-rag).", "display_name": "Read Me", @@ -1181,7 +1019,7 @@ }, "dragging": false, "height": 324, - "id": "note-SHxvt", + "id": "note-Jv9dw", "measured": { "height": 324, "width": 325 @@ -1195,7 +1033,7 @@ "y": 907.6428043837066 }, "resizing": false, - "selected": true, + "selected": false, "style": { "height": 324, "width": 324 @@ -1207,7 +1045,7 @@ "data": { "description": "Display a chat message in the Playground.", "display_name": "Chat Output", - "id": "ChatOutput-aQXd2", + "id": "ChatOutput-71awB", "node": { "base_classes": [ "Message" @@ -1489,7 +1327,7 @@ }, "dragging": false, "height": 234, - "id": "ChatOutput-aQXd2", + "id": "ChatOutput-71awB", "measured": { "height": 234, "width": 320 @@ -1508,7 +1346,7 @@ }, { "data": { - "id": "OpenAIEmbeddings-t4aMI", + "id": "OpenAIEmbeddings-hOLGN", "node": { "base_classes": [ "Embeddings" @@ -1546,7 +1384,7 @@ "frozen": false, "icon": "OpenAI", "legacy": false, - "lf_version": "1.1.1", + "lf_version": "1.2.0", "metadata": {}, "output_types": [], "outputs": [ @@ -1805,7 +1643,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "openai_api_type": { "_input_type": "MessageTextInput", @@ -1988,7 +1826,7 @@ }, "dragging": false, "height": 320, - "id": "OpenAIEmbeddings-t4aMI", + "id": "OpenAIEmbeddings-hOLGN", "measured": { "height": 320, "width": 320 @@ -2007,7 +1845,7 @@ }, { "data": { - "id": "note-PYicu", + "id": "note-mtZZX", "node": { "description": "## 📚 1. Load Data Flow\n\nRun this first! Load data from a local file and embed it into the vector database.\n\nSelect a Database and a Collection, or create new ones. \n\nClick ▶️ **Run component** on the **Astra DB** component to load your data.\n\n* If you're using OSS Langflow, add your Astra DB Application Token to the Astra DB component.\n\n#### Next steps:\n Experiment by changing the prompt and the contextual data to see how the retrieval flow's responses change.", "display_name": "", @@ -2020,7 +1858,7 @@ }, "dragging": false, "height": 324, - "id": "note-PYicu", + "id": "note-mtZZX", "measured": { "height": 324, "width": 325 @@ -2044,7 +1882,7 @@ }, { "data": { - "id": "OpenAIEmbeddings-fftff", + "id": "OpenAIEmbeddings-wJbwl", "node": { "base_classes": [ "Embeddings" @@ -2341,7 +2179,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "openai_api_type": { "_input_type": "MessageTextInput", @@ -2524,7 +2362,7 @@ }, "dragging": false, "height": 320, - "id": "OpenAIEmbeddings-fftff", + "id": "OpenAIEmbeddings-wJbwl", "measured": { "height": 320, "width": 320 @@ -2543,7 +2381,7 @@ }, { "data": { - "id": "File-IwyQk", + "id": "File-acgDn", "node": { "base_classes": [ "Data" @@ -2816,7 +2654,7 @@ }, "dragging": false, "height": 367, - "id": "File-IwyQk", + "id": "File-acgDn", "measured": { "height": 367, "width": 320 @@ -2835,7 +2673,7 @@ }, { "data": { - "id": "note-F2ZXQ", + "id": "note-DADiN", "node": { "description": "### 💡 Add your OpenAI API key here 👇", "display_name": "", @@ -2848,7 +2686,7 @@ }, "dragging": false, "height": 324, - "id": "note-F2ZXQ", + "id": "note-DADiN", "measured": { "height": 324, "width": 324 @@ -2867,7 +2705,7 @@ }, { "data": { - "id": "note-ocedp", + "id": "note-KUeaz", "node": { "description": "### 💡 Add your OpenAI API key here 👇", "display_name": "", @@ -2880,7 +2718,7 @@ }, "dragging": false, "height": 324, - "id": "note-ocedp", + "id": "note-KUeaz", "measured": { "height": 324, "width": 324 @@ -2899,7 +2737,7 @@ }, { "data": { - "id": "note-rhNU3", + "id": "note-fYVNl", "node": { "description": "### 💡 Add your OpenAI API key here 👇", "display_name": "", @@ -2912,7 +2750,7 @@ }, "dragging": false, "height": 324, - "id": "note-rhNU3", + "id": "note-fYVNl", "measured": { "height": 324, "width": 324 @@ -2931,7 +2769,7 @@ }, { "data": { - "id": "OpenAIModel-e49kI", + "id": "OpenAIModel-smg8l", "node": { "base_classes": [ "LanguageModel", @@ -3018,7 +2856,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -3299,7 +3137,7 @@ "type": "OpenAIModel" }, "dragging": false, - "id": "OpenAIModel-e49kI", + "id": "OpenAIModel-smg8l", "measured": { "height": 525, "width": 320 @@ -3313,7 +3151,7 @@ }, { "data": { - "id": "AstraDB-8CuoQ", + "id": "AstraDB-MxkZ3", "node": { "base_classes": [ "Data", @@ -3351,6 +3189,7 @@ "frozen": false, "icon": "AstraDB", "legacy": false, + "lf_version": "1.2.0", "metadata": {}, "minimized": false, "output_types": [], @@ -3542,10 +3381,21 @@ "dialog_inputs": {}, "display_name": "Embedding generation method", "dynamic": false, + "helper_text": "To create collections with more embedding provider options, go to your database in Astra DB.", "info": "Provider to use for generating embeddings.", "name": "embedding_generation_provider", - "options": [], - "options_metadata": [], + "options": [ + "Bring your own", + "Nvidia" + ], + "options_metadata": [ + { + "icon": "vectorstores" + }, + { + "icon": "NVIDIA" + } + ], "placeholder": "", "real_time_refresh": true, "required": true, @@ -3567,14 +3417,15 @@ "name": "embedding_generation_model", "options": [], "options_metadata": [], - "placeholder": "", + "placeholder": null, + "readonly": "", "required": true, "show": true, "title_case": false, "tool_mode": false, "trace_as_metadata": true, "type": "str", - "value": "" + "value": null }, "04_dimension": { "_input_type": "IntInput", @@ -3585,8 +3436,9 @@ "list": false, "list_add_label": "Add More", "name": "dimension", - "placeholder": "", - "required": false, + "placeholder": 1024, + "readonly": true, + "required": "", "show": true, "title_case": false, "tool_mode": false, @@ -3728,7 +3580,14 @@ "info": "The Database name for the Astra DB instance.", "name": "database_name", "options": [], - "options_metadata": [], + "options_metadata": [ + { + "api_endpoint": "https://0c50eb2b-9bfe-4ba6-84d2-e76ac21baab2-us-east-2.apps.astra.datastax.com", + "collections": 5, + "org_id": "3f982720-3bc7-493d-a573-8978d698f2e1", + "status": null + } + ], "placeholder": "", "real_time_refresh": true, "refresh_button": true, @@ -3781,7 +3640,7 @@ "tool_mode": false, "trace_as_metadata": true, "type": "str", - "value": "Embedding Model" + "value": "Astra Vectorize" }, "embedding_model": { "_input_type": "HandleInput", @@ -4001,7 +3860,7 @@ "show": true, "title_case": false, "type": "str", - "value": "ASTRA_DB_APPLICATION_TOKEN" + "value": "" } }, "tool_mode": false @@ -4010,7 +3869,7 @@ "type": "AstraDB" }, "dragging": false, - "id": "AstraDB-8CuoQ", + "id": "AstraDB-MxkZ3", "measured": { "height": 532, "width": 320 @@ -4024,7 +3883,7 @@ }, { "data": { - "id": "AstraDB-JF2lS", + "id": "AstraDB-QiWTk", "node": { "base_classes": [ "Data", @@ -4439,7 +4298,14 @@ "info": "The Database name for the Astra DB instance.", "name": "database_name", "options": [], - "options_metadata": [], + "options_metadata": [ + { + "api_endpoint": "https://0c50eb2b-9bfe-4ba6-84d2-e76ac21baab2-us-east-2.apps.astra.datastax.com", + "collections": 5, + "org_id": "3f982720-3bc7-493d-a573-8978d698f2e1", + "status": null + } + ], "placeholder": "", "real_time_refresh": true, "refresh_button": true, @@ -4712,7 +4578,7 @@ "show": true, "title_case": false, "type": "str", - "value": "ASTRA_DB_APPLICATION_TOKEN" + "value": "" } }, "tool_mode": false @@ -4721,7 +4587,7 @@ "type": "AstraDB" }, "dragging": false, - "id": "AstraDB-JF2lS", + "id": "AstraDB-QiWTk", "measured": { "height": 532, "width": 320 @@ -4732,17 +4598,191 @@ }, "selected": false, "type": "genericNode" + }, + { + "data": { + "id": "parser-UZXIp", + "node": { + "base_classes": [ + "Message" + ], + "beta": false, + "category": "processing", + "conditional_paths": [], + "custom_fields": {}, + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", + "documentation": "", + "edited": false, + "field_order": [ + "mode", + "pattern", + "input_data", + "sep" + ], + "frozen": false, + "icon": "braces", + "key": "parser", + "legacy": false, + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", + "selected": "Message", + "tool_mode": true, + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 2.220446049250313e-16, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n name = \"parser\"\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" + }, + "input_data": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Data or DataFrame", + "dynamic": false, + "info": "Accepts either a DataFrame or a Data object.", + "input_types": [ + "DataFrame", + "Data" + ], + "list": false, + "list_add_label": "Add More", + "name": "input_data", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Parser" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "Text: {text}" + }, + "sep": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Separator", + "dynamic": false, + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "sep", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "\n" + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "parser" + }, + "dragging": false, + "id": "parser-UZXIp", + "measured": { + "height": 395, + "width": 320 + }, + "position": { + "x": 1583.5982144641368, + "y": 651.635660385082 + }, + "selected": false, + "type": "genericNode" } ], "viewport": { - "x": 23.94695899838632, - "y": -121.14595988693713, - "zoom": 0.44406917240373706 + "x": -362.0179700217086, + "y": -239.3395446821612, + "zoom": 0.5898074154736053 } }, "description": "Load your data for chat context with Retrieval Augmented Generation.", "endpoint_name": null, - "id": "b9f87508-ce73-441d-ba7b-66144513c04e", + "id": "6a8c15c1-6212-44d0-9216-e39a8543c7a6", "is_component": false, "last_tested_version": "1.2.0", "name": "Vector Store RAG", diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json b/src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json index 56a4b8112..3ac84f397 100644 --- a/src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json +++ b/src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json @@ -7,7 +7,7 @@ "data": { "sourceHandle": { "dataType": "YouTubeCommentsComponent", - "id": "YouTubeCommentsComponent-1B3Fv", + "id": "YouTubeCommentsComponent-g4VZV", "name": "comments", "output_types": [ "DataFrame" @@ -15,19 +15,19 @@ }, "targetHandle": { "fieldName": "df", - "id": "BatchRunComponent-gNH2h", + "id": "BatchRunComponent-kxOUU", "inputTypes": [ "DataFrame" ], "type": "other" } }, - "id": "reactflow__edge-YouTubeCommentsComponent-1B3Fv{œdataTypeœ:œYouTubeCommentsComponentœ,œidœ:œYouTubeCommentsComponent-1B3Fvœ,œnameœ:œcommentsœ,œoutput_typesœ:[œDataFrameœ]}-BatchRunComponent-gNH2h{œfieldNameœ:œdfœ,œidœ:œBatchRunComponent-gNH2hœ,œinputTypesœ:[œDataFrameœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-YouTubeCommentsComponent-g4VZV{œdataTypeœ:œYouTubeCommentsComponentœ,œidœ:œYouTubeCommentsComponent-g4VZVœ,œnameœ:œcommentsœ,œoutput_typesœ:[œDataFrameœ]}-BatchRunComponent-kxOUU{œfieldNameœ:œdfœ,œidœ:œBatchRunComponent-kxOUUœ,œinputTypesœ:[œDataFrameœ],œtypeœ:œotherœ}", "selected": false, - "source": "YouTubeCommentsComponent-1B3Fv", - "sourceHandle": "{œdataTypeœ: œYouTubeCommentsComponentœ, œidœ: œYouTubeCommentsComponent-1B3Fvœ, œnameœ: œcommentsœ, œoutput_typesœ: [œDataFrameœ]}", - "target": "BatchRunComponent-gNH2h", - "targetHandle": "{œfieldNameœ: œdfœ, œidœ: œBatchRunComponent-gNH2hœ, œinputTypesœ: [œDataFrameœ], œtypeœ: œotherœ}" + "source": "YouTubeCommentsComponent-g4VZV", + "sourceHandle": "{œdataTypeœ: œYouTubeCommentsComponentœ, œidœ: œYouTubeCommentsComponent-g4VZVœ, œnameœ: œcommentsœ, œoutput_typesœ: [œDataFrameœ]}", + "target": "BatchRunComponent-kxOUU", + "targetHandle": "{œfieldNameœ: œdfœ, œidœ: œBatchRunComponent-kxOUUœ, œinputTypesœ: [œDataFrameœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -35,7 +35,7 @@ "data": { "sourceHandle": { "dataType": "OpenAIModel", - "id": "OpenAIModel-05xLQ", + "id": "OpenAIModel-0iBkZ", "name": "model_output", "output_types": [ "LanguageModel" @@ -43,75 +43,19 @@ }, "targetHandle": { "fieldName": "model", - "id": "BatchRunComponent-gNH2h", + "id": "BatchRunComponent-kxOUU", "inputTypes": [ "LanguageModel" ], "type": "other" } }, - "id": "reactflow__edge-OpenAIModel-05xLQ{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-05xLQœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-BatchRunComponent-gNH2h{œfieldNameœ:œmodelœ,œidœ:œBatchRunComponent-gNH2hœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-OpenAIModel-0iBkZ{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-0iBkZœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-BatchRunComponent-kxOUU{œfieldNameœ:œmodelœ,œidœ:œBatchRunComponent-kxOUUœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}", "selected": false, - "source": "OpenAIModel-05xLQ", - "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-05xLQœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", - "target": "BatchRunComponent-gNH2h", - "targetHandle": "{œfieldNameœ: œmodelœ, œidœ: œBatchRunComponent-gNH2hœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "BatchRunComponent", - "id": "BatchRunComponent-gNH2h", - "name": "batch_results", - "output_types": [ - "DataFrame" - ] - }, - "targetHandle": { - "fieldName": "df", - "id": "ParseDataFrame-OIHSx", - "inputTypes": [ - "DataFrame" - ], - "type": "other" - } - }, - "id": "reactflow__edge-BatchRunComponent-gNH2h{œdataTypeœ:œBatchRunComponentœ,œidœ:œBatchRunComponent-gNH2hœ,œnameœ:œbatch_resultsœ,œoutput_typesœ:[œDataFrameœ]}-ParseDataFrame-OIHSx{œfieldNameœ:œdfœ,œidœ:œParseDataFrame-OIHSxœ,œinputTypesœ:[œDataFrameœ],œtypeœ:œotherœ}", - "selected": false, - "source": "BatchRunComponent-gNH2h", - "sourceHandle": "{œdataTypeœ: œBatchRunComponentœ, œidœ: œBatchRunComponent-gNH2hœ, œnameœ: œbatch_resultsœ, œoutput_typesœ: [œDataFrameœ]}", - "target": "ParseDataFrame-OIHSx", - "targetHandle": "{œfieldNameœ: œdfœ, œidœ: œParseDataFrame-OIHSxœ, œinputTypesœ: [œDataFrameœ], œtypeœ: œotherœ}" - }, - { - "animated": false, - "className": "", - "data": { - "sourceHandle": { - "dataType": "ParseDataFrame", - "id": "ParseDataFrame-OIHSx", - "name": "text", - "output_types": [ - "Message" - ] - }, - "targetHandle": { - "fieldName": "analysis", - "id": "Prompt-aWbxe", - "inputTypes": [ - "Message" - ], - "type": "str" - } - }, - "id": "reactflow__edge-ParseDataFrame-OIHSx{œdataTypeœ:œParseDataFrameœ,œidœ:œParseDataFrame-OIHSxœ,œnameœ:œtextœ,œoutput_typesœ:[œMessageœ]}-Prompt-aWbxe{œfieldNameœ:œanalysisœ,œidœ:œPrompt-aWbxeœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", - "selected": false, - "source": "ParseDataFrame-OIHSx", - "sourceHandle": "{œdataTypeœ: œParseDataFrameœ, œidœ: œParseDataFrame-OIHSxœ, œnameœ: œtextœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-aWbxe", - "targetHandle": "{œfieldNameœ: œanalysisœ, œidœ: œPrompt-aWbxeœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "OpenAIModel-0iBkZ", + "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-0iBkZœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}", + "target": "BatchRunComponent-kxOUU", + "targetHandle": "{œfieldNameœ: œmodelœ, œidœ: œBatchRunComponent-kxOUUœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -119,7 +63,7 @@ "data": { "sourceHandle": { "dataType": "Prompt", - "id": "Prompt-aWbxe", + "id": "Prompt-UAMac", "name": "prompt", "output_types": [ "Message" @@ -127,19 +71,19 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "Agent-3FPSt", + "id": "Agent-0gW4Y", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-Prompt-aWbxe{œdataTypeœ:œPromptœ,œidœ:œPrompt-aWbxeœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-Agent-3FPSt{œfieldNameœ:œinput_valueœ,œidœ:œAgent-3FPStœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Prompt-UAMac{œdataTypeœ:œPromptœ,œidœ:œPrompt-UAMacœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-Agent-0gW4Y{œfieldNameœ:œinput_valueœ,œidœ:œAgent-0gW4Yœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Prompt-aWbxe", - "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-aWbxeœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", - "target": "Agent-3FPSt", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAgent-3FPStœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "Prompt-UAMac", + "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-UAMacœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}", + "target": "Agent-0gW4Y", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œAgent-0gW4Yœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -147,7 +91,7 @@ "data": { "sourceHandle": { "dataType": "Agent", - "id": "Agent-3FPSt", + "id": "Agent-0gW4Y", "name": "response", "output_types": [ "Message" @@ -155,7 +99,7 @@ }, "targetHandle": { "fieldName": "input_value", - "id": "ChatOutput-i5hlZ", + "id": "ChatOutput-9nsTW", "inputTypes": [ "Data", "DataFrame", @@ -164,12 +108,12 @@ "type": "str" } }, - "id": "reactflow__edge-Agent-3FPSt{œdataTypeœ:œAgentœ,œidœ:œAgent-3FPStœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-i5hlZ{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-i5hlZœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-Agent-0gW4Y{œdataTypeœ:œAgentœ,œidœ:œAgent-0gW4Yœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-9nsTW{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-9nsTWœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "Agent-3FPSt", - "sourceHandle": "{œdataTypeœ: œAgentœ, œidœ: œAgent-3FPStœ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}", - "target": "ChatOutput-i5hlZ", - "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-i5hlZœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" + "source": "Agent-0gW4Y", + "sourceHandle": "{œdataTypeœ: œAgentœ, œidœ: œAgent-0gW4Yœ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}", + "target": "ChatOutput-9nsTW", + "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-9nsTWœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -177,7 +121,7 @@ "data": { "sourceHandle": { "dataType": "YouTubeTranscripts", - "id": "YouTubeTranscripts-nSvJC", + "id": "YouTubeTranscripts-QMIjk", "name": "component_as_tool", "output_types": [ "Tool" @@ -185,19 +129,19 @@ }, "targetHandle": { "fieldName": "tools", - "id": "Agent-3FPSt", + "id": "Agent-0gW4Y", "inputTypes": [ "Tool" ], "type": "other" } }, - "id": "reactflow__edge-YouTubeTranscripts-nSvJC{œdataTypeœ:œYouTubeTranscriptsœ,œidœ:œYouTubeTranscripts-nSvJCœ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}-Agent-3FPSt{œfieldNameœ:œtoolsœ,œidœ:œAgent-3FPStœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-YouTubeTranscripts-QMIjk{œdataTypeœ:œYouTubeTranscriptsœ,œidœ:œYouTubeTranscripts-QMIjkœ,œnameœ:œcomponent_as_toolœ,œoutput_typesœ:[œToolœ]}-Agent-0gW4Y{œfieldNameœ:œtoolsœ,œidœ:œAgent-0gW4Yœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}", "selected": false, - "source": "YouTubeTranscripts-nSvJC", - "sourceHandle": "{œdataTypeœ: œYouTubeTranscriptsœ, œidœ: œYouTubeTranscripts-nSvJCœ, œnameœ: œcomponent_as_toolœ, œoutput_typesœ: [œToolœ]}", - "target": "Agent-3FPSt", - "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œAgent-3FPStœ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}" + "source": "YouTubeTranscripts-QMIjk", + "sourceHandle": "{œdataTypeœ: œYouTubeTranscriptsœ, œidœ: œYouTubeTranscripts-QMIjkœ, œnameœ: œcomponent_as_toolœ, œoutput_typesœ: [œToolœ]}", + "target": "Agent-0gW4Y", + "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œAgent-0gW4Yœ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}" }, { "animated": false, @@ -205,7 +149,7 @@ "data": { "sourceHandle": { "dataType": "ChatInput", - "id": "ChatInput-aeyrx", + "id": "ChatInput-XErsc", "name": "message", "output_types": [ "Message" @@ -213,19 +157,19 @@ }, "targetHandle": { "fieldName": "input_text", - "id": "ConditionalRouter-DNDns", + "id": "ConditionalRouter-7lzPh", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-ChatInput-aeyrx{œdataTypeœ:œChatInputœ,œidœ:œChatInput-aeyrxœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-ConditionalRouter-DNDns{œfieldNameœ:œinput_textœ,œidœ:œConditionalRouter-DNDnsœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-XErsc{œdataTypeœ:œChatInputœ,œidœ:œChatInput-XErscœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-ConditionalRouter-7lzPh{œfieldNameœ:œinput_textœ,œidœ:œConditionalRouter-7lzPhœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "ChatInput-aeyrx", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-aeyrxœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "ConditionalRouter-DNDns", - "targetHandle": "{œfieldNameœ: œinput_textœ, œidœ: œConditionalRouter-DNDnsœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "ChatInput-XErsc", + "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-XErscœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "ConditionalRouter-7lzPh", + "targetHandle": "{œfieldNameœ: œinput_textœ, œidœ: œConditionalRouter-7lzPhœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -233,7 +177,7 @@ "data": { "sourceHandle": { "dataType": "ChatInput", - "id": "ChatInput-aeyrx", + "id": "ChatInput-XErsc", "name": "message", "output_types": [ "Message" @@ -241,19 +185,19 @@ }, "targetHandle": { "fieldName": "message", - "id": "ConditionalRouter-DNDns", + "id": "ConditionalRouter-7lzPh", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-ChatInput-aeyrx{œdataTypeœ:œChatInputœ,œidœ:œChatInput-aeyrxœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-ConditionalRouter-DNDns{œfieldNameœ:œmessageœ,œidœ:œConditionalRouter-DNDnsœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ChatInput-XErsc{œdataTypeœ:œChatInputœ,œidœ:œChatInput-XErscœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-ConditionalRouter-7lzPh{œfieldNameœ:œmessageœ,œidœ:œConditionalRouter-7lzPhœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "ChatInput-aeyrx", - "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-aeyrxœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", - "target": "ConditionalRouter-DNDns", - "targetHandle": "{œfieldNameœ: œmessageœ, œidœ: œConditionalRouter-DNDnsœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "ChatInput-XErsc", + "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-XErscœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}", + "target": "ConditionalRouter-7lzPh", + "targetHandle": "{œfieldNameœ: œmessageœ, œidœ: œConditionalRouter-7lzPhœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -261,7 +205,7 @@ "data": { "sourceHandle": { "dataType": "ConditionalRouter", - "id": "ConditionalRouter-DNDns", + "id": "ConditionalRouter-7lzPh", "name": "true_result", "output_types": [ "Message" @@ -269,19 +213,19 @@ }, "targetHandle": { "fieldName": "video_url", - "id": "YouTubeCommentsComponent-1B3Fv", + "id": "YouTubeCommentsComponent-g4VZV", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-ConditionalRouter-DNDns{œdataTypeœ:œConditionalRouterœ,œidœ:œConditionalRouter-DNDnsœ,œnameœ:œtrue_resultœ,œoutput_typesœ:[œMessageœ]}-YouTubeCommentsComponent-1B3Fv{œfieldNameœ:œvideo_urlœ,œidœ:œYouTubeCommentsComponent-1B3Fvœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ConditionalRouter-7lzPh{œdataTypeœ:œConditionalRouterœ,œidœ:œConditionalRouter-7lzPhœ,œnameœ:œtrue_resultœ,œoutput_typesœ:[œMessageœ]}-YouTubeCommentsComponent-g4VZV{œfieldNameœ:œvideo_urlœ,œidœ:œYouTubeCommentsComponent-g4VZVœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "ConditionalRouter-DNDns", - "sourceHandle": "{œdataTypeœ: œConditionalRouterœ, œidœ: œConditionalRouter-DNDnsœ, œnameœ: œtrue_resultœ, œoutput_typesœ: [œMessageœ]}", - "target": "YouTubeCommentsComponent-1B3Fv", - "targetHandle": "{œfieldNameœ: œvideo_urlœ, œidœ: œYouTubeCommentsComponent-1B3Fvœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "ConditionalRouter-7lzPh", + "sourceHandle": "{œdataTypeœ: œConditionalRouterœ, œidœ: œConditionalRouter-7lzPhœ, œnameœ: œtrue_resultœ, œoutput_typesœ: [œMessageœ]}", + "target": "YouTubeCommentsComponent-g4VZV", + "targetHandle": "{œfieldNameœ: œvideo_urlœ, œidœ: œYouTubeCommentsComponent-g4VZVœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" }, { "animated": false, @@ -289,7 +233,7 @@ "data": { "sourceHandle": { "dataType": "ConditionalRouter", - "id": "ConditionalRouter-DNDns", + "id": "ConditionalRouter-7lzPh", "name": "true_result", "output_types": [ "Message" @@ -297,25 +241,80 @@ }, "targetHandle": { "fieldName": "url", - "id": "Prompt-aWbxe", + "id": "Prompt-UAMac", "inputTypes": [ "Message" ], "type": "str" } }, - "id": "reactflow__edge-ConditionalRouter-DNDns{œdataTypeœ:œConditionalRouterœ,œidœ:œConditionalRouter-DNDnsœ,œnameœ:œtrue_resultœ,œoutput_typesœ:[œMessageœ]}-Prompt-aWbxe{œfieldNameœ:œurlœ,œidœ:œPrompt-aWbxeœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-ConditionalRouter-7lzPh{œdataTypeœ:œConditionalRouterœ,œidœ:œConditionalRouter-7lzPhœ,œnameœ:œtrue_resultœ,œoutput_typesœ:[œMessageœ]}-Prompt-UAMac{œfieldNameœ:œurlœ,œidœ:œPrompt-UAMacœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", "selected": false, - "source": "ConditionalRouter-DNDns", - "sourceHandle": "{œdataTypeœ: œConditionalRouterœ, œidœ: œConditionalRouter-DNDnsœ, œnameœ: œtrue_resultœ, œoutput_typesœ: [œMessageœ]}", - "target": "Prompt-aWbxe", - "targetHandle": "{œfieldNameœ: œurlœ, œidœ: œPrompt-aWbxeœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + "source": "ConditionalRouter-7lzPh", + "sourceHandle": "{œdataTypeœ: œConditionalRouterœ, œidœ: œConditionalRouter-7lzPhœ, œnameœ: œtrue_resultœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-UAMac", + "targetHandle": "{œfieldNameœ: œurlœ, œidœ: œPrompt-UAMacœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" + }, + { + "animated": false, + "data": { + "sourceHandle": { + "dataType": "BatchRunComponent", + "id": "BatchRunComponent-kxOUU", + "name": "batch_results", + "output_types": [ + "DataFrame" + ] + }, + "targetHandle": { + "fieldName": "input_data", + "id": "parser-r3iNU", + "inputTypes": [ + "DataFrame", + "Data" + ], + "type": "other" + } + }, + "id": "xy-edge__BatchRunComponent-kxOUU{œdataTypeœ:œBatchRunComponentœ,œidœ:œBatchRunComponent-kxOUUœ,œnameœ:œbatch_resultsœ,œoutput_typesœ:[œDataFrameœ]}-parser-r3iNU{œfieldNameœ:œinput_dataœ,œidœ:œparser-r3iNUœ,œinputTypesœ:[œDataFrameœ,œDataœ],œtypeœ:œotherœ}", + "selected": false, + "source": "BatchRunComponent-kxOUU", + "sourceHandle": "{œdataTypeœ: œBatchRunComponentœ, œidœ: œBatchRunComponent-kxOUUœ, œnameœ: œbatch_resultsœ, œoutput_typesœ: [œDataFrameœ]}", + "target": "parser-r3iNU", + "targetHandle": "{œfieldNameœ: œinput_dataœ, œidœ: œparser-r3iNUœ, œinputTypesœ: [œDataFrameœ, œDataœ], œtypeœ: œotherœ}" + }, + { + "animated": false, + "data": { + "sourceHandle": { + "dataType": "parser", + "id": "parser-r3iNU", + "name": "parsed_text", + "output_types": [ + "Message" + ] + }, + "targetHandle": { + "fieldName": "analysis", + "id": "Prompt-UAMac", + "inputTypes": [ + "Message" + ], + "type": "str" + } + }, + "id": "xy-edge__parser-r3iNU{œdataTypeœ:œparserœ,œidœ:œparser-r3iNUœ,œnameœ:œparsed_textœ,œoutput_typesœ:[œMessageœ]}-Prompt-UAMac{œfieldNameœ:œanalysisœ,œidœ:œPrompt-UAMacœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}", + "selected": false, + "source": "parser-r3iNU", + "sourceHandle": "{œdataTypeœ: œparserœ, œidœ: œparser-r3iNUœ, œnameœ: œparsed_textœ, œoutput_typesœ: [œMessageœ]}", + "target": "Prompt-UAMac", + "targetHandle": "{œfieldNameœ: œanalysisœ, œidœ: œPrompt-UAMacœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}" } ], "nodes": [ { "data": { - "id": "BatchRunComponent-gNH2h", + "id": "BatchRunComponent-kxOUU", "node": { "base_classes": [ "DataFrame" @@ -489,7 +488,7 @@ "type": "BatchRunComponent" }, "dragging": false, - "id": "BatchRunComponent-gNH2h", + "id": "BatchRunComponent-kxOUU", "measured": { "height": 399, "width": 320 @@ -503,7 +502,7 @@ }, { "data": { - "id": "YouTubeCommentsComponent-1B3Fv", + "id": "YouTubeCommentsComponent-g4VZV", "node": { "base_classes": [ "DataFrame" @@ -560,7 +559,7 @@ "input_types": [ "Message" ], - "load_from_db": true, + "load_from_db": false, "name": "api_key", "password": true, "placeholder": "", @@ -568,7 +567,7 @@ "show": true, "title_case": false, "type": "str", - "value": "YOUTUBE_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -695,7 +694,7 @@ "type": "YouTubeCommentsComponent" }, "dragging": false, - "id": "YouTubeCommentsComponent-1B3Fv", + "id": "YouTubeCommentsComponent-g4VZV", "measured": { "height": 497, "width": 320 @@ -704,12 +703,12 @@ "x": 191.60600144515274, "y": 6042.239455161904 }, - "selected": true, + "selected": false, "type": "genericNode" }, { "data": { - "id": "OpenAIModel-05xLQ", + "id": "OpenAIModel-0iBkZ", "node": { "base_classes": [ "LanguageModel", @@ -797,7 +796,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -1078,7 +1077,7 @@ "type": "OpenAIModel" }, "dragging": false, - "id": "OpenAIModel-05xLQ", + "id": "OpenAIModel-0iBkZ", "measured": { "height": 525, "width": 320 @@ -1092,156 +1091,7 @@ }, { "data": { - "id": "ParseDataFrame-OIHSx", - "node": { - "base_classes": [ - "Message" - ], - "beta": false, - "category": "processing", - "conditional_paths": [], - "custom_fields": {}, - "description": "Convert a DataFrame into plain text following a specified template. Each column in the DataFrame is treated as a possible template key, e.g. {col_name}.", - "display_name": "Parse DataFrame", - "documentation": "", - "edited": false, - "field_order": [ - "df", - "template", - "sep" - ], - "frozen": false, - "icon": "braces", - "key": "ParseDataFrame", - "legacy": false, - "lf_version": "1.1.3", - "metadata": {}, - "minimized": false, - "output_types": [], - "outputs": [ - { - "allows_loop": false, - "cache": true, - "display_name": "Text", - "method": "parse_data", - "name": "text", - "selected": "Message", - "tool_mode": true, - "types": [ - "Message" - ], - "value": "__UNDEFINED__" - } - ], - "pinned": false, - "score": 0.007568328950209746, - "template": { - "_type": "Component", - "code": { - "advanced": true, - "dynamic": true, - "fileTypes": [], - "file_path": "", - "info": "", - "list": false, - "load_from_db": false, - "multiline": true, - "name": "code", - "password": false, - "placeholder": "", - "required": true, - "show": true, - "title_case": false, - "type": "code", - "value": "from langflow.custom import Component\nfrom langflow.io import DataFrameInput, MultilineInput, Output, StrInput\nfrom langflow.schema.message import Message\n\n\nclass ParseDataFrameComponent(Component):\n display_name = \"Parse DataFrame\"\n description = (\n \"Convert a DataFrame into plain text following a specified template. \"\n \"Each column in the DataFrame is treated as a possible template key, e.g. {col_name}.\"\n )\n icon = \"braces\"\n name = \"ParseDataFrame\"\n\n inputs = [\n DataFrameInput(name=\"df\", display_name=\"DataFrame\", info=\"The DataFrame to convert to text rows.\"),\n MultilineInput(\n name=\"template\",\n display_name=\"Template\",\n info=(\n \"The template for formatting each row. \"\n \"Use placeholders matching column names in the DataFrame, for example '{col1}', '{col2}'.\"\n ),\n value=\"{text}\",\n ),\n StrInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String that joins all row texts when building the single Text output.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Text\",\n name=\"text\",\n info=\"All rows combined into a single text, each row formatted by the template and separated by `sep`.\",\n method=\"parse_data\",\n ),\n ]\n\n def _clean_args(self):\n dataframe = self.df\n template = self.template or \"{text}\"\n sep = self.sep or \"\\n\"\n return dataframe, template, sep\n\n def parse_data(self) -> Message:\n \"\"\"Converts each row of the DataFrame into a formatted string using the template.\n\n then joins them with `sep`. Returns a single combined string as a Message.\n \"\"\"\n dataframe, template, sep = self._clean_args()\n\n lines = []\n # For each row in the DataFrame, build a dict and format\n for _, row in dataframe.iterrows():\n row_dict = row.to_dict()\n text_line = template.format(**row_dict) # e.g. template=\"{text}\", row_dict={\"text\": \"Hello\"}\n lines.append(text_line)\n\n # Join all lines with the provided separator\n result_string = sep.join(lines)\n self.status = result_string # store in self.status for UI logs\n return Message(text=result_string)\n" - }, - "df": { - "_input_type": "DataFrameInput", - "advanced": false, - "display_name": "DataFrame", - "dynamic": false, - "info": "The DataFrame to convert to text rows.", - "input_types": [ - "DataFrame" - ], - "list": false, - "list_add_label": "Add More", - "name": "df", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "other", - "value": "" - }, - "sep": { - "_input_type": "StrInput", - "advanced": true, - "display_name": "Separator", - "dynamic": false, - "info": "String that joins all row texts when building the single Text output.", - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "name": "sep", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_metadata": true, - "type": "str", - "value": "\n" - }, - "template": { - "_input_type": "MultilineInput", - "advanced": false, - "display_name": "Template", - "dynamic": false, - "info": "The template for formatting each row. Use placeholders matching column names in the DataFrame, for example '{col1}', '{col2}'.", - "input_types": [ - "Message" - ], - "list": false, - "list_add_label": "Add More", - "load_from_db": false, - "multiline": true, - "name": "template", - "placeholder": "", - "required": false, - "show": true, - "title_case": false, - "tool_mode": false, - "trace_as_input": true, - "trace_as_metadata": true, - "type": "str", - "value": "{model_response}" - } - }, - "tool_mode": false - }, - "showNode": true, - "type": "ParseDataFrame" - }, - "dragging": false, - "id": "ParseDataFrame-OIHSx", - "measured": { - "height": 334, - "width": 320 - }, - "position": { - "x": 993.5819211529395, - "y": 6076.201261805775 - }, - "selected": false, - "type": "genericNode" - }, - { - "data": { - "id": "Agent-3FPSt", + "id": "Agent-0gW4Y", "node": { "base_classes": [ "Message" @@ -1398,7 +1248,7 @@ "show": true, "title_case": false, "type": "str", - "value": "OPENAI_API_KEY" + "value": "" }, "code": { "advanced": true, @@ -1891,7 +1741,7 @@ "type": "Agent" }, "dragging": false, - "id": "Agent-3FPSt", + "id": "Agent-0gW4Y", "measured": { "height": 624, "width": 320 @@ -1905,7 +1755,7 @@ }, { "data": { - "id": "Prompt-aWbxe", + "id": "Prompt-UAMac", "node": { "base_classes": [ "Message" @@ -2067,7 +1917,7 @@ "type": "Prompt" }, "dragging": false, - "id": "Prompt-aWbxe", + "id": "Prompt-UAMac", "measured": { "height": 495, "width": 320 @@ -2081,7 +1931,7 @@ }, { "data": { - "id": "ChatOutput-i5hlZ", + "id": "ChatOutput-9nsTW", "node": { "base_classes": [ "Message" @@ -2379,7 +2229,7 @@ "type": "ChatOutput" }, "dragging": false, - "id": "ChatOutput-i5hlZ", + "id": "ChatOutput-9nsTW", "measured": { "height": 230, "width": 320 @@ -2393,7 +2243,7 @@ }, { "data": { - "id": "YouTubeTranscripts-nSvJC", + "id": "YouTubeTranscripts-QMIjk", "node": { "base_classes": [ "Data", @@ -2658,7 +2508,7 @@ "type": "YouTubeTranscripts" }, "dragging": false, - "id": "YouTubeTranscripts-nSvJC", + "id": "YouTubeTranscripts-QMIjk", "measured": { "height": 417, "width": 320 @@ -2672,7 +2522,7 @@ }, { "data": { - "id": "ChatInput-aeyrx", + "id": "ChatInput-XErsc", "node": { "base_classes": [ "Message" @@ -2970,7 +2820,7 @@ "type": "ChatInput" }, "dragging": false, - "id": "ChatInput-aeyrx", + "id": "ChatInput-XErsc", "measured": { "height": 230, "width": 320 @@ -2984,7 +2834,7 @@ }, { "data": { - "id": "note-ATxMO", + "id": "note-Cc4Ez", "node": { "description": "# Batch Run component\n\nThis component processes a DataFrame by running each row through a Language Model (LLM). Perfect for batch analysis, sentiment scoring, or content generation at scale.\n\n## How It Works\n1. Accepts a DataFrame with text data.\n2. Routes each row through your chosen LLM.\n3. Returns new DataFrame with `text_input` and `model_response`.\n\n", "display_name": "", @@ -2997,7 +2847,7 @@ }, "dragging": false, "height": 522, - "id": "note-ATxMO", + "id": "note-Cc4Ez", "measured": { "height": 522, "width": 325 @@ -3013,7 +2863,7 @@ }, { "data": { - "id": "note-7bKvt", + "id": "note-fckWh", "node": { "description": "## Set up the YouTube API\n1. Go to [Google Cloud Console](https://console.cloud.google.com).\n2. Create a new project or select existing one.\n3. Enable YouTube Data API v3:\n - Navigate to APIs & Services > Library.\n - Search \"YouTube Data API v3\".\n - Click Enable.\n4. Create credentials:\n - Go to APIs & Services > Credentials.\n - Click Create Credentials > API Key.\n5. Copy your new API key for use in the component.\n\n⚠️ Remember to:\n- Restrict the API key to YouTube Data API v3 only.\n- Set appropriate quotas and restrictions.\n", "display_name": "", @@ -3026,7 +2876,7 @@ }, "dragging": false, "height": 486, - "id": "note-7bKvt", + "id": "note-fckWh", "measured": { "height": 486, "width": 325 @@ -3042,7 +2892,7 @@ }, { "data": { - "id": "note-rMgY5", + "id": "note-FZ1Fg", "node": { "description": "# 🎥 YouTube Video Analysis\nThis flow performs comprehensive analysis of YouTube videos.\n1. Extract video comments and transcripts.\n2. Run sentiment analysis on comments using LLM.\n3. Combine transcript content and comment sentiment for comprehensive video analysis.\n\n## Prerequisites\n- OpenAI API Key\n- YouTube Data API v3 key", "display_name": "", @@ -3055,7 +2905,7 @@ }, "dragging": false, "height": 454, - "id": "note-rMgY5", + "id": "note-FZ1Fg", "measured": { "height": 454, "width": 433 @@ -3071,7 +2921,7 @@ }, { "data": { - "id": "ConditionalRouter-DNDns", + "id": "ConditionalRouter-7lzPh", "node": { "base_classes": [ "Message" @@ -3314,7 +3164,7 @@ "type": "ConditionalRouter" }, "dragging": false, - "id": "ConditionalRouter-DNDns", + "id": "ConditionalRouter-7lzPh", "measured": { "height": 588, "width": 320 @@ -3325,17 +3175,191 @@ }, "selected": false, "type": "genericNode" + }, + { + "data": { + "id": "parser-r3iNU", + "node": { + "base_classes": [ + "Message" + ], + "beta": false, + "category": "processing", + "conditional_paths": [], + "custom_fields": {}, + "description": "Format a DataFrame or Data object into text using a template. Enable 'Stringify' to convert input into a readable string instead.", + "display_name": "Parser", + "documentation": "", + "edited": false, + "field_order": [ + "mode", + "pattern", + "input_data", + "sep" + ], + "frozen": false, + "icon": "braces", + "key": "parser", + "legacy": false, + "metadata": {}, + "minimized": false, + "output_types": [], + "outputs": [ + { + "allows_loop": false, + "cache": true, + "display_name": "Parsed Text", + "method": "parse_combined_text", + "name": "parsed_text", + "selected": "Message", + "tool_mode": true, + "types": [ + "Message" + ], + "value": "__UNDEFINED__" + } + ], + "pinned": false, + "score": 2.220446049250313e-16, + "template": { + "_type": "Component", + "code": { + "advanced": true, + "dynamic": true, + "fileTypes": [], + "file_path": "", + "info": "", + "list": false, + "load_from_db": false, + "multiline": true, + "name": "code", + "password": false, + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "type": "code", + "value": "import json\nfrom typing import Any\n\nfrom langflow.custom import Component\nfrom langflow.io import (\n BoolInput,\n HandleInput,\n MessageTextInput,\n MultilineInput,\n Output,\n TabInput,\n)\nfrom langflow.schema import Data, DataFrame\nfrom langflow.schema.message import Message\n\n\nclass ParserComponent(Component):\n name = \"parser\"\n display_name = \"Parser\"\n description = (\n \"Format a DataFrame or Data object into text using a template. \"\n \"Enable 'Stringify' to convert input into a readable string instead.\"\n )\n icon = \"braces\"\n\n inputs = [\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n formatted_text = self.pattern.format(**data.data)\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def _safe_convert(self, data: Any) -> str:\n \"\"\"Safely convert input data to string.\"\"\"\n try:\n if isinstance(data, str):\n return data\n if isinstance(data, Message):\n return data.get_text()\n if isinstance(data, Data):\n return json.dumps(data.data)\n if isinstance(data, DataFrame):\n if hasattr(self, \"clean_data\") and self.clean_data:\n # Remove empty rows\n data = data.dropna(how=\"all\")\n # Remove empty lines in each cell\n data = data.replace(r\"^\\s*$\", \"\", regex=True)\n # Replace multiple newlines with a single newline\n data = data.replace(r\"\\n+\", \"\\n\", regex=True)\n return data.to_markdown(index=False)\n return str(data)\n except (ValueError, TypeError, AttributeError) as e:\n msg = f\"Error converting data: {e!s}\"\n raise ValueError(msg) from e\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([self._safe_convert(item) for item in self.input_data])\n else:\n result = self._safe_convert(self.input_data)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" + }, + "input_data": { + "_input_type": "HandleInput", + "advanced": false, + "display_name": "Data or DataFrame", + "dynamic": false, + "info": "Accepts either a DataFrame or a Data object.", + "input_types": [ + "DataFrame", + "Data" + ], + "list": false, + "list_add_label": "Add More", + "name": "input_data", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "trace_as_metadata": true, + "type": "other", + "value": "" + }, + "mode": { + "_input_type": "TabInput", + "advanced": false, + "display_name": "Mode", + "dynamic": false, + "info": "Convert into raw string instead of using a template.", + "name": "mode", + "options": [ + "Parser", + "Stringify" + ], + "placeholder": "", + "real_time_refresh": true, + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_metadata": true, + "type": "tab", + "value": "Parser" + }, + "pattern": { + "_input_type": "MultilineInput", + "advanced": false, + "copy_field": false, + "display_name": "Template", + "dynamic": true, + "info": "Use variables within curly brackets to extract column values for DataFrames or key values for Data.For example: `Name: {Name}, Age: {Age}, Country: {Country}`", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "multiline": true, + "name": "pattern", + "placeholder": "", + "required": true, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "{model_response}" + }, + "sep": { + "_input_type": "MessageTextInput", + "advanced": true, + "display_name": "Separator", + "dynamic": false, + "info": "String used to separate rows/items.", + "input_types": [ + "Message" + ], + "list": false, + "list_add_label": "Add More", + "load_from_db": false, + "name": "sep", + "placeholder": "", + "required": false, + "show": true, + "title_case": false, + "tool_mode": false, + "trace_as_input": true, + "trace_as_metadata": true, + "type": "str", + "value": "\n" + } + }, + "tool_mode": false + }, + "showNode": true, + "type": "parser" + }, + "dragging": false, + "id": "parser-r3iNU", + "measured": { + "height": 395, + "width": 320 + }, + "position": { + "x": 1055.5958957337489, + "y": 5951.514633172236 + }, + "selected": false, + "type": "genericNode" } ], "viewport": { - "x": 401.72676890198, - "y": -2953.276665335332, - "zoom": 0.543344895149028 + "x": 69.36235934000024, + "y": -2491.3683867679606, + "zoom": 0.4827961559150896 } }, "description": "The YouTube Analysis flow extracts video comments and transcripts, analyzing sentiment patterns and content themes.", "endpoint_name": null, - "id": "2956e72a-2ad1-4848-aa74-ee9143e6e88e", + "id": "5865d442-4b78-49a2-b561-c29b8286a981", "is_component": false, "last_tested_version": "1.2.0", "name": "Youtube Analysis", diff --git a/src/frontend/tests/core/features/filterEdge-shard-0.spec.ts b/src/frontend/tests/core/features/filterEdge-shard-0.spec.ts index 94c578dff..372729854 100644 --- a/src/frontend/tests/core/features/filterEdge-shard-0.spec.ts +++ b/src/frontend/tests/core/features/filterEdge-shard-0.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from "@playwright/test"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { adjustScreenView } from "../../utils/adjust-screen-view"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; @@ -12,13 +13,7 @@ test( await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("retrievalqa"); - await page.getByTestId("sidebar-options-trigger").click(); - await page - .getByTestId("sidebar-legacy-switch") - .isVisible({ timeout: 5000 }); - await page.getByTestId("sidebar-legacy-switch").click(); - await expect(page.getByTestId("sidebar-legacy-switch")).toBeChecked(); - await page.getByTestId("sidebar-options-trigger").click(); + await addLegacyComponents(page); await page.waitForTimeout(1000); await page diff --git a/src/frontend/tests/core/features/freeze.spec.ts b/src/frontend/tests/core/features/freeze.spec.ts index f20002350..4891d21f4 100644 --- a/src/frontend/tests/core/features/freeze.spec.ts +++ b/src/frontend/tests/core/features/freeze.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from "@playwright/test"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; import { zoomOut } from "../../utils/zoom-out"; @@ -11,8 +12,9 @@ test( await page.getByTestId("blank-flow").click(); - //first component + await addLegacyComponents(page); + //first component await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("text input"); await page.waitForSelector('[data-testid="inputsText Input"]', { diff --git a/src/frontend/tests/core/features/stop-building.spec.ts b/src/frontend/tests/core/features/stop-building.spec.ts index 76a2ad451..2c121efea 100644 --- a/src/frontend/tests/core/features/stop-building.spec.ts +++ b/src/frontend/tests/core/features/stop-building.spec.ts @@ -1,4 +1,5 @@ import { test } from "@playwright/test"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; import { removeOldApiKeys } from "../../utils/remove-old-api-keys"; import { updateOldComponents } from "../../utils/update-old-components"; @@ -11,6 +12,8 @@ test( await awaitBootstrapTest(page); await page.getByTestId("blank-flow").click(); + await addLegacyComponents(page); + //first component await page.getByTestId("sidebar-search-input").click(); diff --git a/src/frontend/tests/core/integrations/Portfolio Website Code Generator.spec.ts b/src/frontend/tests/core/integrations/Portfolio Website Code Generator.spec.ts index 4ce67141e..c9b8c7f07 100644 --- a/src/frontend/tests/core/integrations/Portfolio Website Code Generator.spec.ts +++ b/src/frontend/tests/core/integrations/Portfolio Website Code Generator.spec.ts @@ -71,7 +71,7 @@ withEventDeliveryModes( expect(concatAllText.length).toBeGreaterThan(200); - expect(concatAllText).toContain("div"); - expect(concatAllText).toContain("class="); + expect(concatAllText).toContain("html"); + expect(concatAllText).toContain("body"); }, ); diff --git a/src/frontend/tests/core/integrations/decisionFlow.spec.ts b/src/frontend/tests/core/integrations/decisionFlow.spec.ts index c8a8494be..1fef2601e 100644 --- a/src/frontend/tests/core/integrations/decisionFlow.spec.ts +++ b/src/frontend/tests/core/integrations/decisionFlow.spec.ts @@ -1,6 +1,7 @@ import { test } from "@playwright/test"; import * as dotenv from "dotenv"; import path from "path"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; import { zoomOut } from "../../utils/zoom-out"; @@ -23,17 +24,13 @@ test( }); await page.getByTestId("blank-flow").click(); - await page.getByTestId("sidebar-options-trigger").click(); - await page - .getByTestId("sidebar-legacy-switch") - .isVisible({ timeout: 5000 }); - await page.getByTestId("sidebar-legacy-switch").click(); + await addLegacyComponents(page); //---------------------------------- CHAT INPUT await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("chat input"); await page.waitForSelector('[data-testid="inputsChat Input"]', { - timeout: 500, + timeout: 2000, }); await zoomOut(page, 6); @@ -48,7 +45,7 @@ test( await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("list"); await page.waitForSelector('[data-testid="helpersCreate List"]', { - timeout: 500, + timeout: 2000, }); await page .getByTestId("helpersCreate List") @@ -97,7 +94,7 @@ test( await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("data to message"); await page.waitForSelector('[data-testid="processingData to Message"]', { - timeout: 500, + timeout: 2000, }); await page .getByTestId("processingData to Message") @@ -114,7 +111,7 @@ test( await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("pass"); await page.waitForSelector('[data-testid="logicPass"]', { - timeout: 500, + timeout: 2000, }); await page .getByTestId("logicPass") @@ -122,13 +119,13 @@ test( targetPosition: { x: 800, y: 100 }, }); await page.waitForSelector('[data-testid="logicPass"]', { - timeout: 500, + timeout: 2000, }); //---------------------------------- PASS await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("pass"); await page.waitForSelector('[data-testid="logicPass"]', { - timeout: 500, + timeout: 2000, }); await page .getByTestId("logicPass") @@ -136,13 +133,13 @@ test( targetPosition: { x: 50, y: 200 }, }); await page.waitForSelector('[data-testid="logicPass"]', { - timeout: 500, + timeout: 2000, }); //---------------------------------- PASS await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("pass"); await page.waitForSelector('[data-testid="logicPass"]', { - timeout: 500, + timeout: 2000, }); await page .getByTestId("logicPass") @@ -150,13 +147,13 @@ test( targetPosition: { x: 200, y: 300 }, }); await page.waitForSelector('[data-testid="logicPass"]', { - timeout: 500, + timeout: 2000, }); //---------------------------------- PROMPT await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("prompt"); await page.waitForSelector('[data-testid="promptsPrompt"]', { - timeout: 500, + timeout: 2000, }); await page .getByTestId("promptsPrompt") @@ -168,7 +165,7 @@ test( await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("openai"); await page.waitForSelector('[data-testid="modelsOpenAI"]', { - timeout: 500, + timeout: 2000, }); await page .getByTestId("modelsOpenAI") @@ -180,7 +177,7 @@ test( await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("if else"); await page.waitForSelector('[data-testid="logicIf-Else"]', { - timeout: 500, + timeout: 2000, }); await page .getByTestId("logicIf-Else") @@ -191,7 +188,7 @@ test( await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("chat output"); await page.waitForSelector('[data-testid="outputsChat Output"]', { - timeout: 500, + timeout: 2000, }); await page .getByTestId("outputsChat Output") @@ -199,13 +196,13 @@ test( targetPosition: { x: 800, y: 300 }, }); await page.waitForSelector('[data-testid="outputsChat Output"]', { - timeout: 500, + timeout: 2000, }); //---------------------------------- CHAT OUTPUT await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("chat output"); await page.waitForSelector('[data-testid="outputsChat Output"]', { - timeout: 500, + timeout: 2000, }); await page .getByTestId("outputsChat Output") @@ -213,7 +210,7 @@ test( targetPosition: { x: 800, y: 400 }, }); await page.waitForSelector('[data-testid="outputsChat Output"]', { - timeout: 500, + timeout: 2000, }); //---------------------------------- await page.getByTestId("fit_view").click(); diff --git a/src/frontend/tests/core/integrations/similarity.spec.ts b/src/frontend/tests/core/integrations/similarity.spec.ts index 21cd4932e..19f599329 100644 --- a/src/frontend/tests/core/integrations/similarity.spec.ts +++ b/src/frontend/tests/core/integrations/similarity.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from "@playwright/test"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; import { updateOldComponents } from "../../utils/update-old-components"; import { zoomOut } from "../../utils/zoom-out"; @@ -16,7 +17,10 @@ test( await page.getByTestId("blank-flow").click(); + await addLegacyComponents(page); + //first component + await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("openai embedding"); await page.waitForSelector("text=OpenAI Embeddings", { diff --git a/src/frontend/tests/core/regression/generalBugs-shard-9.spec.ts b/src/frontend/tests/core/regression/generalBugs-shard-9.spec.ts index 9e8045ffe..91605ce88 100644 --- a/src/frontend/tests/core/regression/generalBugs-shard-9.spec.ts +++ b/src/frontend/tests/core/regression/generalBugs-shard-9.spec.ts @@ -1,6 +1,7 @@ import { expect, test } from "@playwright/test"; import * as dotenv from "dotenv"; import path from "path"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; import { initialGPTsetup } from "../../utils/initialGPTsetup"; test( @@ -28,11 +29,7 @@ test( await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("message history"); - await page.getByTestId("sidebar-options-trigger").click(); - await page - .getByTestId("sidebar-legacy-switch") - .isVisible({ timeout: 5000 }); - await page.getByTestId("sidebar-legacy-switch").click(); + await addLegacyComponents(page); // Locate the canvas element const canvas = page.locator("#react-flow-id"); // Update the selector if needed diff --git a/src/frontend/tests/core/unit/codeAreaModalComponent.spec.ts b/src/frontend/tests/core/unit/codeAreaModalComponent.spec.ts index e0a0d5ebe..815dbbee0 100644 --- a/src/frontend/tests/core/unit/codeAreaModalComponent.spec.ts +++ b/src/frontend/tests/core/unit/codeAreaModalComponent.spec.ts @@ -1,4 +1,5 @@ import { test } from "@playwright/test"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; test( @@ -19,11 +20,7 @@ test( timeout: 3000, }); - await page.getByTestId("sidebar-options-trigger").click(); - await page - .getByTestId("sidebar-legacy-switch") - .isVisible({ timeout: 5000 }); - await page.getByTestId("sidebar-legacy-switch").click(); + await addLegacyComponents(page); await page.waitForSelector('[data-testid="prototypesPython Function"]', { timeout: 3000, diff --git a/src/frontend/tests/core/unit/fileUploadComponent.spec.ts b/src/frontend/tests/core/unit/fileUploadComponent.spec.ts index 06817180f..f7b8272e8 100644 --- a/src/frontend/tests/core/unit/fileUploadComponent.spec.ts +++ b/src/frontend/tests/core/unit/fileUploadComponent.spec.ts @@ -1,6 +1,7 @@ import { expect, test } from "@playwright/test"; import fs from "fs"; import path from "path"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { adjustScreenView } from "../../utils/adjust-screen-view"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; import { generateRandomFilename } from "../../utils/generate-filename"; @@ -29,6 +30,8 @@ test( }); await page.getByTestId("blank-flow").click(); + await addLegacyComponents(page); + await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("file"); diff --git a/src/frontend/tests/core/unit/nestedComponent.spec.ts b/src/frontend/tests/core/unit/nestedComponent.spec.ts index 5511fc285..ac306b16c 100644 --- a/src/frontend/tests/core/unit/nestedComponent.spec.ts +++ b/src/frontend/tests/core/unit/nestedComponent.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from "@playwright/test"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { adjustScreenView } from "../../utils/adjust-screen-view"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; @@ -15,13 +16,7 @@ test( await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("alter metadata"); - await page.getByTestId("sidebar-options-trigger").click(); - await page - .getByTestId("sidebar-legacy-switch") - .isVisible({ timeout: 5000 }); - await page.getByTestId("sidebar-legacy-switch").click(); - await expect(page.getByTestId("sidebar-legacy-switch")).toBeChecked(); - await page.getByTestId("sidebar-options-trigger").click(); + await addLegacyComponents(page); await page.waitForTimeout(500); diff --git a/src/frontend/tests/extended/features/filterEdge-shard-1.spec.ts b/src/frontend/tests/extended/features/filterEdge-shard-1.spec.ts index f3f3f5bd0..9d51b63c5 100644 --- a/src/frontend/tests/extended/features/filterEdge-shard-1.spec.ts +++ b/src/frontend/tests/extended/features/filterEdge-shard-1.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from "@playwright/test"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { adjustScreenView } from "../../utils/adjust-screen-view"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; @@ -14,14 +15,7 @@ test( timeout: 3000, }); - await page.getByTestId("sidebar-options-trigger").click(); - - await expect(page.getByTestId("sidebar-legacy-switch")).toBeVisible({ - timeout: 5000, - }); - await page.getByTestId("sidebar-legacy-switch").click(); - await expect(page.getByTestId("sidebar-legacy-switch")).toBeChecked(); - await page.getByTestId("sidebar-options-trigger").click(); + await addLegacyComponents(page); await page.getByTestId("sidebar-search-input").click(); await page.getByTestId("sidebar-search-input").fill("retrievalqa"); diff --git a/src/frontend/tests/extended/features/loop-component.spec.ts b/src/frontend/tests/extended/features/loop-component.spec.ts index 20cabfa32..0175d40e9 100644 --- a/src/frontend/tests/extended/features/loop-component.spec.ts +++ b/src/frontend/tests/extended/features/loop-component.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from "@playwright/test"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; import { zoomOut } from "../../utils/zoom-out"; @@ -9,6 +10,8 @@ test( await awaitBootstrapTest(page); await page.getByTestId("blank-flow").click(); + await addLegacyComponents(page); + await page.waitForSelector( '[data-testid="sidebar-custom-component-button"]', { @@ -146,13 +149,23 @@ test( .first() .click(); + await zoomOut(page, 4); + await page.getByTestId("div-generic-node").nth(5).click(); await page.waitForTimeout(1000); + await page.waitForSelector('[data-testid="more-options-modal"]', { + timeout: 100000, + }); + await page.getByTestId("more-options-modal").click(); - await page.waitForTimeout(500); + await page.waitForTimeout(1000); + + await page.waitForSelector('[data-testid="expand-button-modal"]', { + timeout: 100000, + }); await page.getByTestId("expand-button-modal").click(); diff --git a/src/frontend/tests/extended/regression/generalBugs-shard-12.spec.ts b/src/frontend/tests/extended/regression/generalBugs-shard-12.spec.ts index ab89cf9e6..75cf1968d 100644 --- a/src/frontend/tests/extended/regression/generalBugs-shard-12.spec.ts +++ b/src/frontend/tests/extended/regression/generalBugs-shard-12.spec.ts @@ -1,4 +1,5 @@ import { expect, test } from "@playwright/test"; +import { addLegacyComponents } from "../../utils/add-legacy-components"; import { awaitBootstrapTest } from "../../utils/await-bootstrap-test"; test( @@ -18,13 +19,7 @@ test( timeout: 30000, }); - await page.getByTestId("sidebar-options-trigger").click(); - await page - .getByTestId("sidebar-legacy-switch") - .isVisible({ timeout: 5000 }); - await page.getByTestId("sidebar-legacy-switch").click(); - await expect(page.getByTestId("sidebar-legacy-switch")).toBeChecked(); - await page.getByTestId("sidebar-options-trigger").click(); + await addLegacyComponents(page); let modelElement = await page.getByTestId( "langchain_utilitiesRetrieverTool", diff --git a/src/frontend/tests/utils/add-legacy-components.ts b/src/frontend/tests/utils/add-legacy-components.ts new file mode 100644 index 000000000..b399574c2 --- /dev/null +++ b/src/frontend/tests/utils/add-legacy-components.ts @@ -0,0 +1,9 @@ +import { expect, Page } from "playwright/test"; + +export const addLegacyComponents = async (page: Page) => { + await page.getByTestId("sidebar-options-trigger").click(); + await page.getByTestId("sidebar-legacy-switch").isVisible({ timeout: 5000 }); + await page.getByTestId("sidebar-legacy-switch").click(); + await expect(page.getByTestId("sidebar-legacy-switch")).toBeChecked(); + await page.getByTestId("sidebar-options-trigger").click(); +};