From ae096a31678e56c49839f4448cc9e3861accae88 Mon Sep 17 00:00:00 2001
From: Cristhian Zanforlin Lousa
<72977554+Cristhianzl@users.noreply.github.com>
Date: Mon, 22 Jul 2024 18:30:30 -0300
Subject: [PATCH] test: add new tests based on new basic examples + vector
store tests (#2879)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* 🔧 (.github/workflows/typescript_test.yml): add BRAVE_SEARCH_API_KEY secret to workflow environment variables
✨ (frontend/src/modals/IOModal/components/chatView/chatMessage/index.tsx): add data-testid attribute to div element for testing purposes
✨ (frontend/tests/end-to-end/Hierarchical Tasks Agent.spec.ts): add end-to-end test for Hierarchical Tasks Agent
✨ (frontend/tests/end-to-end/Sequential Tasks Agent.spec.ts): add end-to-end test for Sequential Tasks Agent
* updating hierarchical task json
* 🔧 (.github/workflows/typescript_test.yml): add secrets for ASTRA_DB_APPLICATION_TOKEN and ASTRA_DB_API_ENDPOINT
♻️ (playwright.config.ts): refactor timeout value to 3 minutes
📝 (Complex Agent.spec.ts): update test to use BRAVE_SEARCH_API_KEY instead of OPENAI_API_KEY
📝 (Complex Agent.spec.ts): update test to use "apple" instead of "agile"
📝 (Hierarchical Tasks Agent.spec.ts): update test to use "langflow" instead of "agile"
📝 (Sequential Tasks Agent.spec.ts): update test to use waitForTimeout instead of isVisible
✨ (Vector Store.spec.ts): Add checks to skip tests if required environment variables are not set
🔧 (Vector Store.spec.ts): Update test logic to fill in required environment variables before running tests to ensure proper test execution
---
.github/workflows/typescript_test.yml | 3 +
.../starter_projects/Hierarchical Agent.json | 675 ++++++++++--------
src/frontend/playwright.config.ts | 2 +-
.../components/chatView/chatMessage/index.tsx | 5 +-
.../tests/end-to-end/Complex Agent.spec.ts | 102 +++
.../Hierarchical Tasks Agent.spec.ts | 106 +++
.../end-to-end/Sequential Tasks Agent.spec.ts | 106 +++
.../tests/end-to-end/Vector Store.spec.ts | 163 +++--
8 files changed, 775 insertions(+), 387 deletions(-)
create mode 100644 src/frontend/tests/end-to-end/Complex Agent.spec.ts
create mode 100644 src/frontend/tests/end-to-end/Hierarchical Tasks Agent.spec.ts
create mode 100644 src/frontend/tests/end-to-end/Sequential Tasks Agent.spec.ts
diff --git a/.github/workflows/typescript_test.yml b/.github/workflows/typescript_test.yml
index 4803762b1..c8c395ab0 100644
--- a/.github/workflows/typescript_test.yml
+++ b/.github/workflows/typescript_test.yml
@@ -56,6 +56,9 @@ jobs:
env:
OPENAI_API_KEY: ${{ inputs.openai_api_key || secrets.OPENAI_API_KEY }}
STORE_API_KEY: ${{ inputs.store_api_key || secrets.STORE_API_KEY }}
+ BRAVE_SEARCH_API_KEY: "${{ secrets.BRAVE_SEARCH_API_KEY }}"
+ ASTRA_DB_APPLICATION_TOKEN: "${{ secrets.ASTRA_DB_APPLICATION_TOKEN }}"
+ ASTRA_DB_API_ENDPOINT: "${{ secrets.ASTRA_DB_API_ENDPOINT }}"
outputs:
failed: ${{ steps.check-failure.outputs.failed }}
steps:
diff --git a/src/backend/base/langflow/initial_setup/starter_projects/Hierarchical Agent.json b/src/backend/base/langflow/initial_setup/starter_projects/Hierarchical Agent.json
index ddf73aafd..daa00bdd7 100644
--- a/src/backend/base/langflow/initial_setup/starter_projects/Hierarchical Agent.json
+++ b/src/backend/base/langflow/initial_setup/starter_projects/Hierarchical Agent.json
@@ -6,7 +6,7 @@
"data": {
"sourceHandle": {
"dataType": "HierarchicalCrewComponent",
- "id": "HierarchicalCrewComponent-JNKGT",
+ "id": "HierarchicalCrewComponent-Y0Uvf",
"name": "output",
"output_types": [
"Message"
@@ -14,26 +14,26 @@
},
"targetHandle": {
"fieldName": "input_value",
- "id": "ChatOutput-IACYe",
+ "id": "ChatOutput-VzVJK",
"inputTypes": [
"Message"
],
"type": "str"
}
},
- "id": "reactflow__edge-HierarchicalCrewComponent-JNKGT{œdataTypeœ:œHierarchicalCrewComponentœ,œidœ:œHierarchicalCrewComponent-JNKGTœ,œnameœ:œoutputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-IACYe{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-IACYeœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
+ "id": "reactflow__edge-HierarchicalCrewComponent-Y0Uvf{œdataTypeœ:œHierarchicalCrewComponentœ,œidœ:œHierarchicalCrewComponent-Y0Uvfœ,œnameœ:œoutputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-VzVJK{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-VzVJKœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
"selected": false,
- "source": "HierarchicalCrewComponent-JNKGT",
- "sourceHandle": "{œdataTypeœ: œHierarchicalCrewComponentœ, œidœ: œHierarchicalCrewComponent-JNKGTœ, œnameœ: œoutputœ, œoutput_typesœ: [œMessageœ]}",
- "target": "ChatOutput-IACYe",
- "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-IACYeœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
+ "source": "HierarchicalCrewComponent-Y0Uvf",
+ "sourceHandle": "{œdataTypeœ: œHierarchicalCrewComponentœ, œidœ: œHierarchicalCrewComponent-Y0Uvfœ, œnameœ: œoutputœ, œoutput_typesœ: [œMessageœ]}",
+ "target": "ChatOutput-VzVJK",
+ "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-VzVJKœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
},
{
"className": "",
"data": {
"sourceHandle": {
"dataType": "HierarchicalTaskComponent",
- "id": "HierarchicalTaskComponent-vvJXu",
+ "id": "HierarchicalTaskComponent-hE8H5",
"name": "task_output",
"output_types": [
"HierarchicalTask"
@@ -41,26 +41,26 @@
},
"targetHandle": {
"fieldName": "tasks",
- "id": "HierarchicalCrewComponent-JNKGT",
+ "id": "HierarchicalCrewComponent-Y0Uvf",
"inputTypes": [
"HierarchicalTask"
],
"type": "other"
}
},
- "id": "reactflow__edge-HierarchicalTaskComponent-vvJXu{œdataTypeœ:œHierarchicalTaskComponentœ,œidœ:œHierarchicalTaskComponent-vvJXuœ,œnameœ:œtask_outputœ,œoutput_typesœ:[œHierarchicalTaskœ]}-HierarchicalCrewComponent-JNKGT{œfieldNameœ:œtasksœ,œidœ:œHierarchicalCrewComponent-JNKGTœ,œinputTypesœ:[œHierarchicalTaskœ],œtypeœ:œotherœ}",
+ "id": "reactflow__edge-HierarchicalTaskComponent-hE8H5{œdataTypeœ:œHierarchicalTaskComponentœ,œidœ:œHierarchicalTaskComponent-hE8H5œ,œnameœ:œtask_outputœ,œoutput_typesœ:[œHierarchicalTaskœ]}-HierarchicalCrewComponent-Y0Uvf{œfieldNameœ:œtasksœ,œidœ:œHierarchicalCrewComponent-Y0Uvfœ,œinputTypesœ:[œHierarchicalTaskœ],œtypeœ:œotherœ}",
"selected": false,
- "source": "HierarchicalTaskComponent-vvJXu",
- "sourceHandle": "{œdataTypeœ: œHierarchicalTaskComponentœ, œidœ: œHierarchicalTaskComponent-vvJXuœ, œnameœ: œtask_outputœ, œoutput_typesœ: [œHierarchicalTaskœ]}",
- "target": "HierarchicalCrewComponent-JNKGT",
- "targetHandle": "{œfieldNameœ: œtasksœ, œidœ: œHierarchicalCrewComponent-JNKGTœ, œinputTypesœ: [œHierarchicalTaskœ], œtypeœ: œotherœ}"
+ "source": "HierarchicalTaskComponent-hE8H5",
+ "sourceHandle": "{œdataTypeœ: œHierarchicalTaskComponentœ, œidœ: œHierarchicalTaskComponent-hE8H5œ, œnameœ: œtask_outputœ, œoutput_typesœ: [œHierarchicalTaskœ]}",
+ "target": "HierarchicalCrewComponent-Y0Uvf",
+ "targetHandle": "{œfieldNameœ: œtasksœ, œidœ: œHierarchicalCrewComponent-Y0Uvfœ, œinputTypesœ: [œHierarchicalTaskœ], œtypeœ: œotherœ}"
},
{
"className": "",
"data": {
"sourceHandle": {
"dataType": "CrewAIAgentComponent",
- "id": "CrewAIAgentComponent-XU5MB",
+ "id": "CrewAIAgentComponent-EbpXd",
"name": "output",
"output_types": [
"Agent"
@@ -68,26 +68,26 @@
},
"targetHandle": {
"fieldName": "agents",
- "id": "HierarchicalCrewComponent-JNKGT",
+ "id": "HierarchicalCrewComponent-Y0Uvf",
"inputTypes": [
"Agent"
],
"type": "other"
}
},
- "id": "reactflow__edge-CrewAIAgentComponent-XU5MB{œdataTypeœ:œCrewAIAgentComponentœ,œidœ:œCrewAIAgentComponent-XU5MBœ,œnameœ:œoutputœ,œoutput_typesœ:[œAgentœ]}-HierarchicalCrewComponent-JNKGT{œfieldNameœ:œagentsœ,œidœ:œHierarchicalCrewComponent-JNKGTœ,œinputTypesœ:[œAgentœ],œtypeœ:œotherœ}",
+ "id": "reactflow__edge-CrewAIAgentComponent-EbpXd{œdataTypeœ:œCrewAIAgentComponentœ,œidœ:œCrewAIAgentComponent-EbpXdœ,œnameœ:œoutputœ,œoutput_typesœ:[œAgentœ]}-HierarchicalCrewComponent-Y0Uvf{œfieldNameœ:œagentsœ,œidœ:œHierarchicalCrewComponent-Y0Uvfœ,œinputTypesœ:[œAgentœ],œtypeœ:œotherœ}",
"selected": false,
- "source": "CrewAIAgentComponent-XU5MB",
- "sourceHandle": "{œdataTypeœ: œCrewAIAgentComponentœ, œidœ: œCrewAIAgentComponent-XU5MBœ, œnameœ: œoutputœ, œoutput_typesœ: [œAgentœ]}",
- "target": "HierarchicalCrewComponent-JNKGT",
- "targetHandle": "{œfieldNameœ: œagentsœ, œidœ: œHierarchicalCrewComponent-JNKGTœ, œinputTypesœ: [œAgentœ], œtypeœ: œotherœ}"
+ "source": "CrewAIAgentComponent-EbpXd",
+ "sourceHandle": "{œdataTypeœ: œCrewAIAgentComponentœ, œidœ: œCrewAIAgentComponent-EbpXdœ, œnameœ: œoutputœ, œoutput_typesœ: [œAgentœ]}",
+ "target": "HierarchicalCrewComponent-Y0Uvf",
+ "targetHandle": "{œfieldNameœ: œagentsœ, œidœ: œHierarchicalCrewComponent-Y0Uvfœ, œinputTypesœ: [œAgentœ], œtypeœ: œotherœ}"
},
{
"className": "",
"data": {
"sourceHandle": {
"dataType": "OpenAIModel",
- "id": "OpenAIModel-xoZ41",
+ "id": "OpenAIModel-Yjtpu",
"name": "model_output",
"output_types": [
"LanguageModel"
@@ -95,26 +95,26 @@
},
"targetHandle": {
"fieldName": "llm",
- "id": "CrewAIAgentComponent-XU5MB",
+ "id": "CrewAIAgentComponent-EbpXd",
"inputTypes": [
"LanguageModel"
],
"type": "other"
}
},
- "id": "reactflow__edge-OpenAIModel-xoZ41{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-xoZ41œ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-CrewAIAgentComponent-XU5MB{œfieldNameœ:œllmœ,œidœ:œCrewAIAgentComponent-XU5MBœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}",
+ "id": "reactflow__edge-OpenAIModel-Yjtpu{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-Yjtpuœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-CrewAIAgentComponent-EbpXd{œfieldNameœ:œllmœ,œidœ:œCrewAIAgentComponent-EbpXdœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}",
"selected": false,
- "source": "OpenAIModel-xoZ41",
- "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-xoZ41œ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}",
- "target": "CrewAIAgentComponent-XU5MB",
- "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œCrewAIAgentComponent-XU5MBœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}"
+ "source": "OpenAIModel-Yjtpu",
+ "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-Yjtpuœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}",
+ "target": "CrewAIAgentComponent-EbpXd",
+ "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œCrewAIAgentComponent-EbpXdœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}"
},
{
"className": "",
"data": {
"sourceHandle": {
"dataType": "CrewAIAgentComponent",
- "id": "CrewAIAgentComponent-Trkfd",
+ "id": "CrewAIAgentComponent-9D8ao",
"name": "output",
"output_types": [
"Agent"
@@ -122,26 +122,26 @@
},
"targetHandle": {
"fieldName": "manager_agent",
- "id": "HierarchicalCrewComponent-JNKGT",
+ "id": "HierarchicalCrewComponent-Y0Uvf",
"inputTypes": [
"Agent"
],
"type": "other"
}
},
- "id": "reactflow__edge-CrewAIAgentComponent-Trkfd{œdataTypeœ:œCrewAIAgentComponentœ,œidœ:œCrewAIAgentComponent-Trkfdœ,œnameœ:œoutputœ,œoutput_typesœ:[œAgentœ]}-HierarchicalCrewComponent-JNKGT{œfieldNameœ:œmanager_agentœ,œidœ:œHierarchicalCrewComponent-JNKGTœ,œinputTypesœ:[œAgentœ],œtypeœ:œotherœ}",
+ "id": "reactflow__edge-CrewAIAgentComponent-9D8ao{œdataTypeœ:œCrewAIAgentComponentœ,œidœ:œCrewAIAgentComponent-9D8aoœ,œnameœ:œoutputœ,œoutput_typesœ:[œAgentœ]}-HierarchicalCrewComponent-Y0Uvf{œfieldNameœ:œmanager_agentœ,œidœ:œHierarchicalCrewComponent-Y0Uvfœ,œinputTypesœ:[œAgentœ],œtypeœ:œotherœ}",
"selected": false,
- "source": "CrewAIAgentComponent-Trkfd",
- "sourceHandle": "{œdataTypeœ: œCrewAIAgentComponentœ, œidœ: œCrewAIAgentComponent-Trkfdœ, œnameœ: œoutputœ, œoutput_typesœ: [œAgentœ]}",
- "target": "HierarchicalCrewComponent-JNKGT",
- "targetHandle": "{œfieldNameœ: œmanager_agentœ, œidœ: œHierarchicalCrewComponent-JNKGTœ, œinputTypesœ: [œAgentœ], œtypeœ: œotherœ}"
+ "source": "CrewAIAgentComponent-9D8ao",
+ "sourceHandle": "{œdataTypeœ: œCrewAIAgentComponentœ, œidœ: œCrewAIAgentComponent-9D8aoœ, œnameœ: œoutputœ, œoutput_typesœ: [œAgentœ]}",
+ "target": "HierarchicalCrewComponent-Y0Uvf",
+ "targetHandle": "{œfieldNameœ: œmanager_agentœ, œidœ: œHierarchicalCrewComponent-Y0Uvfœ, œinputTypesœ: [œAgentœ], œtypeœ: œotherœ}"
},
{
"className": "",
"data": {
"sourceHandle": {
"dataType": "OpenAIModel",
- "id": "OpenAIModel-0cqIu",
+ "id": "OpenAIModel-HgNnu",
"name": "model_output",
"output_types": [
"LanguageModel"
@@ -149,26 +149,26 @@
},
"targetHandle": {
"fieldName": "llm",
- "id": "CrewAIAgentComponent-Trkfd",
+ "id": "CrewAIAgentComponent-9D8ao",
"inputTypes": [
"LanguageModel"
],
"type": "other"
}
},
- "id": "reactflow__edge-OpenAIModel-0cqIu{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-0cqIuœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-CrewAIAgentComponent-Trkfd{œfieldNameœ:œllmœ,œidœ:œCrewAIAgentComponent-Trkfdœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}",
+ "id": "reactflow__edge-OpenAIModel-HgNnu{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-HgNnuœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-CrewAIAgentComponent-9D8ao{œfieldNameœ:œllmœ,œidœ:œCrewAIAgentComponent-9D8aoœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}",
"selected": false,
- "source": "OpenAIModel-0cqIu",
- "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-0cqIuœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}",
- "target": "CrewAIAgentComponent-Trkfd",
- "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œCrewAIAgentComponent-Trkfdœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}"
+ "source": "OpenAIModel-HgNnu",
+ "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-HgNnuœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}",
+ "target": "CrewAIAgentComponent-9D8ao",
+ "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œCrewAIAgentComponent-9D8aoœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}"
},
{
"className": "",
"data": {
"sourceHandle": {
"dataType": "Prompt",
- "id": "Prompt-5o2wP",
+ "id": "Prompt-eqGhn",
"name": "prompt",
"output_types": [
"Message"
@@ -176,25 +176,25 @@
},
"targetHandle": {
"fieldName": "task_description",
- "id": "HierarchicalTaskComponent-vvJXu",
+ "id": "HierarchicalTaskComponent-hE8H5",
"inputTypes": [
"Message"
],
"type": "str"
}
},
- "id": "reactflow__edge-Prompt-5o2wP{œdataTypeœ:œPromptœ,œidœ:œPrompt-5o2wPœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-HierarchicalTaskComponent-vvJXu{œfieldNameœ:œtask_descriptionœ,œidœ:œHierarchicalTaskComponent-vvJXuœ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
- "source": "Prompt-5o2wP",
- "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-5o2wPœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}",
- "target": "HierarchicalTaskComponent-vvJXu",
- "targetHandle": "{œfieldNameœ: œtask_descriptionœ, œidœ: œHierarchicalTaskComponent-vvJXuœ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
+ "id": "reactflow__edge-Prompt-eqGhn{œdataTypeœ:œPromptœ,œidœ:œPrompt-eqGhnœ,œnameœ:œpromptœ,œoutput_typesœ:[œMessageœ]}-HierarchicalTaskComponent-hE8H5{œfieldNameœ:œtask_descriptionœ,œidœ:œHierarchicalTaskComponent-hE8H5œ,œinputTypesœ:[œMessageœ],œtypeœ:œstrœ}",
+ "source": "Prompt-eqGhn",
+ "sourceHandle": "{œdataTypeœ: œPromptœ, œidœ: œPrompt-eqGhnœ, œnameœ: œpromptœ, œoutput_typesœ: [œMessageœ]}",
+ "target": "HierarchicalTaskComponent-hE8H5",
+ "targetHandle": "{œfieldNameœ: œtask_descriptionœ, œidœ: œHierarchicalTaskComponent-hE8H5œ, œinputTypesœ: [œMessageœ], œtypeœ: œstrœ}"
},
{
"className": "",
"data": {
"sourceHandle": {
"dataType": "ChatInput",
- "id": "ChatInput-kHOLm",
+ "id": "ChatInput-xgRl9",
"name": "message",
"output_types": [
"Message"
@@ -202,7 +202,7 @@
},
"targetHandle": {
"fieldName": "query",
- "id": "Prompt-5o2wP",
+ "id": "Prompt-eqGhn",
"inputTypes": [
"Message",
"Text"
@@ -210,45 +210,18 @@
"type": "str"
}
},
- "id": "reactflow__edge-ChatInput-kHOLm{œdataTypeœ:œChatInputœ,œidœ:œChatInput-kHOLmœ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Prompt-5o2wP{œfieldNameœ:œqueryœ,œidœ:œPrompt-5o2wPœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}",
- "source": "ChatInput-kHOLm",
- "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-kHOLmœ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}",
- "target": "Prompt-5o2wP",
- "targetHandle": "{œfieldNameœ: œqueryœ, œidœ: œPrompt-5o2wPœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}"
- },
- {
- "className": "",
- "data": {
- "sourceHandle": {
- "dataType": "SearchAPITool",
- "id": "SearchAPITool-fmETj",
- "name": "tool",
- "output_types": [
- "Tool"
- ]
- },
- "targetHandle": {
- "fieldName": "tools",
- "id": "CrewAIAgentComponent-XU5MB",
- "inputTypes": [
- "Tool"
- ],
- "type": "other"
- }
- },
- "id": "reactflow__edge-SearchAPITool-fmETj{œdataTypeœ:œSearchAPIToolœ,œidœ:œSearchAPITool-fmETjœ,œnameœ:œtoolœ,œoutput_typesœ:[œToolœ]}-CrewAIAgentComponent-XU5MB{œfieldNameœ:œtoolsœ,œidœ:œCrewAIAgentComponent-XU5MBœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}",
- "selected": false,
- "source": "SearchAPITool-fmETj",
- "sourceHandle": "{œdataTypeœ: œSearchAPIToolœ, œidœ: œSearchAPITool-fmETjœ, œnameœ: œtoolœ, œoutput_typesœ: [œToolœ]}",
- "target": "CrewAIAgentComponent-XU5MB",
- "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œCrewAIAgentComponent-XU5MBœ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}"
+ "id": "reactflow__edge-ChatInput-xgRl9{œdataTypeœ:œChatInputœ,œidœ:œChatInput-xgRl9œ,œnameœ:œmessageœ,œoutput_typesœ:[œMessageœ]}-Prompt-eqGhn{œfieldNameœ:œqueryœ,œidœ:œPrompt-eqGhnœ,œinputTypesœ:[œMessageœ,œTextœ],œtypeœ:œstrœ}",
+ "source": "ChatInput-xgRl9",
+ "sourceHandle": "{œdataTypeœ: œChatInputœ, œidœ: œChatInput-xgRl9œ, œnameœ: œmessageœ, œoutput_typesœ: [œMessageœ]}",
+ "target": "Prompt-eqGhn",
+ "targetHandle": "{œfieldNameœ: œqueryœ, œidœ: œPrompt-eqGhnœ, œinputTypesœ: [œMessageœ, œTextœ], œtypeœ: œstrœ}"
},
{
"className": "",
"data": {
"sourceHandle": {
"dataType": "CrewAIAgentComponent",
- "id": "CrewAIAgentComponent-V2kfR",
+ "id": "CrewAIAgentComponent-UMpxO",
"name": "output",
"output_types": [
"Agent"
@@ -256,25 +229,25 @@
},
"targetHandle": {
"fieldName": "agents",
- "id": "HierarchicalCrewComponent-JNKGT",
+ "id": "HierarchicalCrewComponent-Y0Uvf",
"inputTypes": [
"Agent"
],
"type": "other"
}
},
- "id": "reactflow__edge-CrewAIAgentComponent-V2kfR{œdataTypeœ:œCrewAIAgentComponentœ,œidœ:œCrewAIAgentComponent-V2kfRœ,œnameœ:œoutputœ,œoutput_typesœ:[œAgentœ]}-HierarchicalCrewComponent-JNKGT{œfieldNameœ:œagentsœ,œidœ:œHierarchicalCrewComponent-JNKGTœ,œinputTypesœ:[œAgentœ],œtypeœ:œotherœ}",
- "source": "CrewAIAgentComponent-V2kfR",
- "sourceHandle": "{œdataTypeœ: œCrewAIAgentComponentœ, œidœ: œCrewAIAgentComponent-V2kfRœ, œnameœ: œoutputœ, œoutput_typesœ: [œAgentœ]}",
- "target": "HierarchicalCrewComponent-JNKGT",
- "targetHandle": "{œfieldNameœ: œagentsœ, œidœ: œHierarchicalCrewComponent-JNKGTœ, œinputTypesœ: [œAgentœ], œtypeœ: œotherœ}"
+ "id": "reactflow__edge-CrewAIAgentComponent-UMpxO{œdataTypeœ:œCrewAIAgentComponentœ,œidœ:œCrewAIAgentComponent-UMpxOœ,œnameœ:œoutputœ,œoutput_typesœ:[œAgentœ]}-HierarchicalCrewComponent-Y0Uvf{œfieldNameœ:œagentsœ,œidœ:œHierarchicalCrewComponent-Y0Uvfœ,œinputTypesœ:[œAgentœ],œtypeœ:œotherœ}",
+ "source": "CrewAIAgentComponent-UMpxO",
+ "sourceHandle": "{œdataTypeœ: œCrewAIAgentComponentœ, œidœ: œCrewAIAgentComponent-UMpxOœ, œnameœ: œoutputœ, œoutput_typesœ: [œAgentœ]}",
+ "target": "HierarchicalCrewComponent-Y0Uvf",
+ "targetHandle": "{œfieldNameœ: œagentsœ, œidœ: œHierarchicalCrewComponent-Y0Uvfœ, œinputTypesœ: [œAgentœ], œtypeœ: œotherœ}"
},
{
"className": "",
"data": {
"sourceHandle": {
"dataType": "OpenAIModel",
- "id": "OpenAIModel-xoZ41",
+ "id": "OpenAIModel-Yjtpu",
"name": "model_output",
"output_types": [
"LanguageModel"
@@ -282,18 +255,44 @@
},
"targetHandle": {
"fieldName": "llm",
- "id": "CrewAIAgentComponent-V2kfR",
+ "id": "CrewAIAgentComponent-UMpxO",
"inputTypes": [
"LanguageModel"
],
"type": "other"
}
},
- "id": "reactflow__edge-OpenAIModel-xoZ41{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-xoZ41œ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-CrewAIAgentComponent-V2kfR{œfieldNameœ:œllmœ,œidœ:œCrewAIAgentComponent-V2kfRœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}",
- "source": "OpenAIModel-xoZ41",
- "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-xoZ41œ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}",
- "target": "CrewAIAgentComponent-V2kfR",
- "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œCrewAIAgentComponent-V2kfRœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}"
+ "id": "reactflow__edge-OpenAIModel-Yjtpu{œdataTypeœ:œOpenAIModelœ,œidœ:œOpenAIModel-Yjtpuœ,œnameœ:œmodel_outputœ,œoutput_typesœ:[œLanguageModelœ]}-CrewAIAgentComponent-UMpxO{œfieldNameœ:œllmœ,œidœ:œCrewAIAgentComponent-UMpxOœ,œinputTypesœ:[œLanguageModelœ],œtypeœ:œotherœ}",
+ "source": "OpenAIModel-Yjtpu",
+ "sourceHandle": "{œdataTypeœ: œOpenAIModelœ, œidœ: œOpenAIModel-Yjtpuœ, œnameœ: œmodel_outputœ, œoutput_typesœ: [œLanguageModelœ]}",
+ "target": "CrewAIAgentComponent-UMpxO",
+ "targetHandle": "{œfieldNameœ: œllmœ, œidœ: œCrewAIAgentComponent-UMpxOœ, œinputTypesœ: [œLanguageModelœ], œtypeœ: œotherœ}"
+ },
+ {
+ "className": "",
+ "data": {
+ "sourceHandle": {
+ "dataType": "SearchAPI",
+ "id": "SearchAPI-Yokat",
+ "name": "api_build_tool",
+ "output_types": [
+ "Tool"
+ ]
+ },
+ "targetHandle": {
+ "fieldName": "tools",
+ "id": "CrewAIAgentComponent-EbpXd",
+ "inputTypes": [
+ "Tool"
+ ],
+ "type": "other"
+ }
+ },
+ "id": "reactflow__edge-SearchAPI-Yokat{œdataTypeœ:œSearchAPIœ,œidœ:œSearchAPI-Yokatœ,œnameœ:œapi_build_toolœ,œoutput_typesœ:[œToolœ]}-CrewAIAgentComponent-EbpXd{œfieldNameœ:œtoolsœ,œidœ:œCrewAIAgentComponent-EbpXdœ,œinputTypesœ:[œToolœ],œtypeœ:œotherœ}",
+ "source": "SearchAPI-Yokat",
+ "sourceHandle": "{œdataTypeœ: œSearchAPIœ, œidœ: œSearchAPI-Yokatœ, œnameœ: œapi_build_toolœ, œoutput_typesœ: [œToolœ]}",
+ "target": "CrewAIAgentComponent-EbpXd",
+ "targetHandle": "{œfieldNameœ: œtoolsœ, œidœ: œCrewAIAgentComponent-EbpXdœ, œinputTypesœ: [œToolœ], œtypeœ: œotherœ}"
}
],
"nodes": [
@@ -301,7 +300,7 @@
"data": {
"description": "Represents a group of agents, defining how they should collaborate and the tasks they should perform.",
"display_name": "Hierarchical Crew",
- "id": "HierarchicalCrewComponent-JNKGT",
+ "id": "HierarchicalCrewComponent-Y0Uvf",
"node": {
"base_classes": [
"Message"
@@ -532,19 +531,21 @@
"type": "HierarchicalCrewComponent"
},
"dragging": false,
- "height": 459,
- "id": "HierarchicalCrewComponent-JNKGT",
+ "height": 516,
+ "id": "HierarchicalCrewComponent-Y0Uvf",
"position": {
"x": 568,
"y": 352.296875
},
"selected": false,
"type": "genericNode",
- "width": 384
+ "width": 432
},
{
"data": {
- "id": "OpenAIModel-xoZ41",
+ "description": "Generates text using OpenAI LLMs.",
+ "display_name": "OpenAI",
+ "id": "OpenAIModel-Yjtpu",
"node": {
"base_classes": [
"LanguageModel",
@@ -559,16 +560,16 @@
"edited": false,
"field_order": [
"input_value",
+ "system_message",
+ "stream",
"max_tokens",
"model_kwargs",
"json_mode",
"output_schema",
"model_name",
"openai_api_base",
- "openai_api_key",
+ "api_key",
"temperature",
- "stream",
- "system_message",
"seed"
],
"frozen": false,
@@ -601,6 +602,22 @@
"pinned": false,
"template": {
"_type": "Component",
+ "api_key": {
+ "advanced": false,
+ "display_name": "OpenAI API Key",
+ "dynamic": false,
+ "info": "The OpenAI API Key to use for the OpenAI model.",
+ "input_types": [],
+ "load_from_db": false,
+ "name": "api_key",
+ "password": true,
+ "placeholder": "",
+ "required": false,
+ "show": true,
+ "title_case": false,
+ "type": "str",
+ "value": ""
+ },
"code": {
"advanced": true,
"dynamic": true,
@@ -617,7 +634,7 @@
"show": true,
"title_case": false,
"type": "code",
- "value": "import operator\nfrom functools import reduce\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import LanguageModel\nfrom langflow.inputs import (\n BoolInput,\n DictInput,\n DropdownInput,\n FloatInput,\n IntInput,\n MessageInput,\n SecretStrInput,\n StrInput,\n)\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n name = \"OpenAIModel\"\n\n inputs = [\n MessageInput(name=\"input_value\", display_name=\"Input\"),\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n advanced=True,\n info=\"If True, it will output JSON regardless of passing a schema.\",\n ),\n DictInput(\n name=\"output_schema\",\n is_list=True,\n display_name=\"Schema\",\n advanced=True,\n info=\"The schema for the Output of the model. You must pass the word JSON in the prompt. If left blank, JSON mode will be disabled.\",\n ),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n BoolInput(name=\"stream\", display_name=\"Stream\", info=STREAM_INFO_TEXT, advanced=True),\n StrInput(\n name=\"system_message\",\n display_name=\"System Message\",\n info=\"System message to pass to the model.\",\n advanced=True,\n ),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\n ),\n ]\n\n def build_model(self) -> LanguageModel: # type: ignore[type-var]\n # self.output_schea is a list of dictionarie s\n # let's convert it to a dictionary\n output_schema_dict: dict[str, str] = reduce(operator.ior, self.output_schema or {}, {})\n openai_api_key = self.openai_api_key\n temperature = self.temperature\n model_name: str = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs or {}\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n json_mode = bool(output_schema_dict) or self.json_mode\n seed = self.seed\n model_kwargs[\"seed\"] = seed\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n )\n if json_mode:\n if output_schema_dict:\n output = output.with_structured_output(schema=output_schema_dict, method=\"json_mode\") # type: ignore\n else:\n output = output.bind(response_format={\"type\": \"json_object\"}) # type: ignore\n\n return output # type: ignore\n\n def _get_exception_message(self, e: Exception):\n \"\"\"\n Get a message from an OpenAI exception.\n\n Args:\n exception (Exception): The exception to get the message from.\n\n Returns:\n str: The message from the exception.\n \"\"\"\n\n try:\n from openai import BadRequestError\n except ImportError:\n return\n if isinstance(e, BadRequestError):\n message = e.body.get(\"message\") # type: ignore\n if message:\n return message\n return\n"
+ "value": "import operator\nfrom functools import reduce\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import LanguageModel\nfrom langflow.inputs import (\n BoolInput,\n DictInput,\n DropdownInput,\n FloatInput,\n IntInput,\n SecretStrInput,\n StrInput,\n)\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n name = \"OpenAIModel\"\n\n inputs = LCModelComponent._base_inputs + [\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n advanced=True,\n info=\"If True, it will output JSON regardless of passing a schema.\",\n ),\n DictInput(\n name=\"output_schema\",\n is_list=True,\n display_name=\"Schema\",\n advanced=True,\n info=\"The schema for the Output of the model. You must pass the word JSON in the prompt. If left blank, JSON mode will be disabled.\",\n ),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\n ),\n ]\n\n def build_model(self) -> LanguageModel: # type: ignore[type-var]\n # self.output_schema is a list of dictionaries\n # let's convert it to a dictionary\n output_schema_dict: dict[str, str] = reduce(operator.ior, self.output_schema or {}, {})\n openai_api_key = self.api_key\n temperature = self.temperature\n model_name: str = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs or {}\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n json_mode = bool(output_schema_dict) or self.json_mode\n seed = self.seed\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n seed=seed,\n )\n if json_mode:\n if output_schema_dict:\n output = output.with_structured_output(schema=output_schema_dict, method=\"json_mode\") # type: ignore\n else:\n output = output.bind(response_format={\"type\": \"json_object\"}) # type: ignore\n\n return output # type: ignore\n\n def _get_exception_message(self, e: Exception):\n \"\"\"\n Get a message from an OpenAI exception.\n\n Args:\n exception (Exception): The exception to get the message from.\n\n Returns:\n str: The message from the exception.\n \"\"\"\n\n try:\n from openai import BadRequestError\n except ImportError:\n return\n if isinstance(e, BadRequestError):\n message = e.body.get(\"message\") # type: ignore\n if message:\n return message\n return\n"
},
"input_value": {
"advanced": false,
@@ -689,8 +706,10 @@
"display_name": "Model Name",
"dynamic": false,
"info": "",
+ "load_from_db": false,
"name": "model_name",
"options": [
+ "gpt-4o-mini",
"gpt-4o",
"gpt-4-turbo",
"gpt-4-turbo-preview",
@@ -704,7 +723,7 @@
"title_case": false,
"trace_as_metadata": true,
"type": "str",
- "value": "gpt-3.5-turbo"
+ "value": "gpt-4o"
},
"openai_api_base": {
"advanced": true,
@@ -722,22 +741,6 @@
"type": "str",
"value": ""
},
- "openai_api_key": {
- "advanced": false,
- "display_name": "OpenAI API Key",
- "dynamic": false,
- "info": "The OpenAI API Key to use for the OpenAI model.",
- "input_types": [],
- "load_from_db": true,
- "name": "openai_api_key",
- "password": true,
- "placeholder": "",
- "required": false,
- "show": true,
- "title_case": false,
- "type": "str",
- "value": ""
- },
"output_schema": {
"advanced": true,
"display_name": "Schema",
@@ -788,6 +791,9 @@
"display_name": "System Message",
"dynamic": false,
"info": "System message to pass to the model.",
+ "input_types": [
+ "Message"
+ ],
"list": false,
"load_from_db": false,
"name": "system_message",
@@ -795,6 +801,7 @@
"required": false,
"show": true,
"title_case": false,
+ "trace_as_input": true,
"trace_as_metadata": true,
"type": "str",
"value": ""
@@ -819,8 +826,8 @@
"type": "OpenAIModel"
},
"dragging": false,
- "height": 623,
- "id": "OpenAIModel-xoZ41",
+ "height": 700,
+ "id": "OpenAIModel-Yjtpu",
"position": {
"x": -1222.8457213471152,
"y": 699.9983009041272
@@ -831,13 +838,13 @@
},
"selected": false,
"type": "genericNode",
- "width": 384
+ "width": 432
},
{
"data": {
"description": "Display a chat message in the Playground.",
"display_name": "Chat Output",
- "id": "ChatOutput-IACYe",
+ "id": "ChatOutput-VzVJK",
"node": {
"base_classes": [
"Message"
@@ -1012,8 +1019,8 @@
"type": "ChatOutput"
},
"dragging": false,
- "height": 309,
- "id": "ChatOutput-IACYe",
+ "height": 347,
+ "id": "ChatOutput-VzVJK",
"position": {
"x": 1070.9148596889393,
"y": 499.80777483894144
@@ -1024,13 +1031,13 @@
},
"selected": false,
"type": "genericNode",
- "width": 384
+ "width": 432
},
{
"data": {
"description": "Each task must have a description, an expected output and an agent responsible for execution.",
"display_name": "Hierarchical Task",
- "id": "HierarchicalTaskComponent-vvJXu",
+ "id": "HierarchicalTaskComponent-hE8H5",
"node": {
"base_classes": [
"HierarchicalTask"
@@ -1149,8 +1156,8 @@
"type": "HierarchicalTaskComponent"
},
"dragging": false,
- "height": 455,
- "id": "HierarchicalTaskComponent-vvJXu",
+ "height": 480,
+ "id": "HierarchicalTaskComponent-hE8H5",
"position": {
"x": 63.673086094601445,
"y": -375.5883288441139
@@ -1161,13 +1168,13 @@
},
"selected": false,
"type": "genericNode",
- "width": 384
+ "width": 432
},
{
"data": {
"description": "Represents an agent of CrewAI.",
"display_name": "CrewAI Agent",
- "id": "CrewAIAgentComponent-XU5MB",
+ "id": "CrewAIAgentComponent-EbpXd",
"node": {
"base_classes": [
"Agent"
@@ -1407,8 +1414,8 @@
"type": "CrewAIAgentComponent"
},
"dragging": false,
- "height": 665,
- "id": "CrewAIAgentComponent-XU5MB",
+ "height": 746,
+ "id": "CrewAIAgentComponent-EbpXd",
"position": {
"x": -479.3544836211363,
"y": 184.85118314299666
@@ -1419,13 +1426,13 @@
},
"selected": false,
"type": "genericNode",
- "width": 384
+ "width": 432
},
{
"data": {
"description": "Represents an agent of CrewAI.",
"display_name": "CrewAI Agent",
- "id": "CrewAIAgentComponent-Trkfd",
+ "id": "CrewAIAgentComponent-9D8ao",
"node": {
"base_classes": [
"Agent"
@@ -1665,8 +1672,8 @@
"type": "CrewAIAgentComponent"
},
"dragging": false,
- "height": 665,
- "id": "CrewAIAgentComponent-Trkfd",
+ "height": 746,
+ "id": "CrewAIAgentComponent-9D8ao",
"position": {
"x": -451.69853654304495,
"y": 1664.003205846104
@@ -1677,11 +1684,13 @@
},
"selected": false,
"type": "genericNode",
- "width": 384
+ "width": 432
},
{
"data": {
- "id": "OpenAIModel-0cqIu",
+ "description": "Generates text using OpenAI LLMs.",
+ "display_name": "OpenAI",
+ "id": "OpenAIModel-HgNnu",
"node": {
"base_classes": [
"LanguageModel",
@@ -1696,16 +1705,16 @@
"edited": false,
"field_order": [
"input_value",
+ "system_message",
+ "stream",
"max_tokens",
"model_kwargs",
"json_mode",
"output_schema",
"model_name",
"openai_api_base",
- "openai_api_key",
+ "api_key",
"temperature",
- "stream",
- "system_message",
"seed"
],
"frozen": false,
@@ -1738,6 +1747,22 @@
"pinned": false,
"template": {
"_type": "Component",
+ "api_key": {
+ "advanced": false,
+ "display_name": "OpenAI API Key",
+ "dynamic": false,
+ "info": "The OpenAI API Key to use for the OpenAI model.",
+ "input_types": [],
+ "load_from_db": false,
+ "name": "api_key",
+ "password": true,
+ "placeholder": "",
+ "required": false,
+ "show": true,
+ "title_case": false,
+ "type": "str",
+ "value": ""
+ },
"code": {
"advanced": true,
"dynamic": true,
@@ -1754,7 +1779,7 @@
"show": true,
"title_case": false,
"type": "code",
- "value": "import operator\nfrom functools import reduce\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.constants import STREAM_INFO_TEXT\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import LanguageModel\nfrom langflow.inputs import (\n BoolInput,\n DictInput,\n DropdownInput,\n FloatInput,\n IntInput,\n MessageInput,\n SecretStrInput,\n StrInput,\n)\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n name = \"OpenAIModel\"\n\n inputs = [\n MessageInput(name=\"input_value\", display_name=\"Input\"),\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n advanced=True,\n info=\"If True, it will output JSON regardless of passing a schema.\",\n ),\n DictInput(\n name=\"output_schema\",\n is_list=True,\n display_name=\"Schema\",\n advanced=True,\n info=\"The schema for the Output of the model. You must pass the word JSON in the prompt. If left blank, JSON mode will be disabled.\",\n ),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n BoolInput(name=\"stream\", display_name=\"Stream\", info=STREAM_INFO_TEXT, advanced=True),\n StrInput(\n name=\"system_message\",\n display_name=\"System Message\",\n info=\"System message to pass to the model.\",\n advanced=True,\n ),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\n ),\n ]\n\n def build_model(self) -> LanguageModel: # type: ignore[type-var]\n # self.output_schea is a list of dictionarie s\n # let's convert it to a dictionary\n output_schema_dict: dict[str, str] = reduce(operator.ior, self.output_schema or {}, {})\n openai_api_key = self.openai_api_key\n temperature = self.temperature\n model_name: str = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs or {}\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n json_mode = bool(output_schema_dict) or self.json_mode\n seed = self.seed\n model_kwargs[\"seed\"] = seed\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n )\n if json_mode:\n if output_schema_dict:\n output = output.with_structured_output(schema=output_schema_dict, method=\"json_mode\") # type: ignore\n else:\n output = output.bind(response_format={\"type\": \"json_object\"}) # type: ignore\n\n return output # type: ignore\n\n def _get_exception_message(self, e: Exception):\n \"\"\"\n Get a message from an OpenAI exception.\n\n Args:\n exception (Exception): The exception to get the message from.\n\n Returns:\n str: The message from the exception.\n \"\"\"\n\n try:\n from openai import BadRequestError\n except ImportError:\n return\n if isinstance(e, BadRequestError):\n message = e.body.get(\"message\") # type: ignore\n if message:\n return message\n return\n"
+ "value": "import operator\nfrom functools import reduce\n\nfrom langchain_openai import ChatOpenAI\nfrom pydantic.v1 import SecretStr\n\nfrom langflow.base.models.model import LCModelComponent\nfrom langflow.base.models.openai_constants import MODEL_NAMES\nfrom langflow.field_typing import LanguageModel\nfrom langflow.inputs import (\n BoolInput,\n DictInput,\n DropdownInput,\n FloatInput,\n IntInput,\n SecretStrInput,\n StrInput,\n)\n\n\nclass OpenAIModelComponent(LCModelComponent):\n display_name = \"OpenAI\"\n description = \"Generates text using OpenAI LLMs.\"\n icon = \"OpenAI\"\n name = \"OpenAIModel\"\n\n inputs = LCModelComponent._base_inputs + [\n IntInput(\n name=\"max_tokens\",\n display_name=\"Max Tokens\",\n advanced=True,\n info=\"The maximum number of tokens to generate. Set to 0 for unlimited tokens.\",\n ),\n DictInput(name=\"model_kwargs\", display_name=\"Model Kwargs\", advanced=True),\n BoolInput(\n name=\"json_mode\",\n display_name=\"JSON Mode\",\n advanced=True,\n info=\"If True, it will output JSON regardless of passing a schema.\",\n ),\n DictInput(\n name=\"output_schema\",\n is_list=True,\n display_name=\"Schema\",\n advanced=True,\n info=\"The schema for the Output of the model. You must pass the word JSON in the prompt. If left blank, JSON mode will be disabled.\",\n ),\n DropdownInput(\n name=\"model_name\", display_name=\"Model Name\", advanced=False, options=MODEL_NAMES, value=MODEL_NAMES[0]\n ),\n StrInput(\n name=\"openai_api_base\",\n display_name=\"OpenAI API Base\",\n advanced=True,\n info=\"The base URL of the OpenAI API. Defaults to https://api.openai.com/v1. You can change this to use other APIs like JinaChat, LocalAI and Prem.\",\n ),\n SecretStrInput(\n name=\"api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n advanced=False,\n value=\"OPENAI_API_KEY\",\n ),\n FloatInput(name=\"temperature\", display_name=\"Temperature\", value=0.1),\n IntInput(\n name=\"seed\",\n display_name=\"Seed\",\n info=\"The seed controls the reproducibility of the job.\",\n advanced=True,\n value=1,\n ),\n ]\n\n def build_model(self) -> LanguageModel: # type: ignore[type-var]\n # self.output_schema is a list of dictionaries\n # let's convert it to a dictionary\n output_schema_dict: dict[str, str] = reduce(operator.ior, self.output_schema or {}, {})\n openai_api_key = self.api_key\n temperature = self.temperature\n model_name: str = self.model_name\n max_tokens = self.max_tokens\n model_kwargs = self.model_kwargs or {}\n openai_api_base = self.openai_api_base or \"https://api.openai.com/v1\"\n json_mode = bool(output_schema_dict) or self.json_mode\n seed = self.seed\n\n if openai_api_key:\n api_key = SecretStr(openai_api_key)\n else:\n api_key = None\n output = ChatOpenAI(\n max_tokens=max_tokens or None,\n model_kwargs=model_kwargs,\n model=model_name,\n base_url=openai_api_base,\n api_key=api_key,\n temperature=temperature or 0.1,\n seed=seed,\n )\n if json_mode:\n if output_schema_dict:\n output = output.with_structured_output(schema=output_schema_dict, method=\"json_mode\") # type: ignore\n else:\n output = output.bind(response_format={\"type\": \"json_object\"}) # type: ignore\n\n return output # type: ignore\n\n def _get_exception_message(self, e: Exception):\n \"\"\"\n Get a message from an OpenAI exception.\n\n Args:\n exception (Exception): The exception to get the message from.\n\n Returns:\n str: The message from the exception.\n \"\"\"\n\n try:\n from openai import BadRequestError\n except ImportError:\n return\n if isinstance(e, BadRequestError):\n message = e.body.get(\"message\") # type: ignore\n if message:\n return message\n return\n"
},
"input_value": {
"advanced": false,
@@ -1826,8 +1851,10 @@
"display_name": "Model Name",
"dynamic": false,
"info": "",
+ "load_from_db": false,
"name": "model_name",
"options": [
+ "gpt-4o-mini",
"gpt-4o",
"gpt-4-turbo",
"gpt-4-turbo-preview",
@@ -1859,22 +1886,6 @@
"type": "str",
"value": ""
},
- "openai_api_key": {
- "advanced": false,
- "display_name": "OpenAI API Key",
- "dynamic": false,
- "info": "The OpenAI API Key to use for the OpenAI model.",
- "input_types": [],
- "load_from_db": true,
- "name": "openai_api_key",
- "password": true,
- "placeholder": "",
- "required": false,
- "show": true,
- "title_case": false,
- "type": "str",
- "value": ""
- },
"output_schema": {
"advanced": true,
"display_name": "Schema",
@@ -1925,6 +1936,9 @@
"display_name": "System Message",
"dynamic": false,
"info": "System message to pass to the model.",
+ "input_types": [
+ "Message"
+ ],
"list": false,
"load_from_db": false,
"name": "system_message",
@@ -1932,6 +1946,7 @@
"required": false,
"show": true,
"title_case": false,
+ "trace_as_input": true,
"trace_as_metadata": true,
"type": "str",
"value": ""
@@ -1956,8 +1971,8 @@
"type": "OpenAIModel"
},
"dragging": false,
- "height": 623,
- "id": "OpenAIModel-0cqIu",
+ "height": 700,
+ "id": "OpenAIModel-HgNnu",
"position": {
"x": -1157.0105401589535,
"y": 1699.4665001507685
@@ -1968,13 +1983,13 @@
},
"selected": false,
"type": "genericNode",
- "width": 384
+ "width": 432
},
{
"data": {
"description": "Create a prompt template with dynamic variables.",
"display_name": "Prompt",
- "id": "Prompt-5o2wP",
+ "id": "Prompt-eqGhn",
"node": {
"base_classes": [
"Message"
@@ -2081,8 +2096,8 @@
"type": "Prompt"
},
"dragging": false,
- "height": 423,
- "id": "Prompt-5o2wP",
+ "height": 475,
+ "id": "Prompt-eqGhn",
"position": {
"x": -561.9017558579421,
"y": -433.5913161630874
@@ -2093,11 +2108,11 @@
},
"selected": false,
"type": "genericNode",
- "width": 384
+ "width": 432
},
{
"data": {
- "id": "ChatInput-kHOLm",
+ "id": "ChatInput-xgRl9",
"node": {
"base_classes": [
"Message"
@@ -2294,154 +2309,25 @@
"type": "ChatInput"
},
"dragging": false,
- "height": 309,
- "id": "ChatInput-kHOLm",
+ "height": 347,
+ "id": "ChatInput-xgRl9",
"position": {
- "x": -1142.1418710409707,
- "y": -372.98153583376074
+ "x": -1227.1161422332996,
+ "y": -380.26504479310324
},
"positionAbsolute": {
- "x": -1142.1418710409707,
- "y": -372.98153583376074
+ "x": -1227.1161422332996,
+ "y": -380.26504479310324
},
"selected": false,
"type": "genericNode",
- "width": 384
- },
- {
- "data": {
- "id": "SearchAPITool-fmETj",
- "node": {
- "base_classes": [
- "BaseTool",
- "Generic",
- "object",
- "Runnable",
- "RunnableSerializable",
- "Serializable",
- "Tool"
- ],
- "beta": false,
- "conditional_paths": [],
- "custom_fields": {
- "api_key": null,
- "engine": null
- },
- "description": "Real-time search engine results API.",
- "display_name": "SearchApi Tool",
- "documentation": "https://www.searchapi.io/docs/google",
- "edited": false,
- "field_order": [
- "engine",
- "api_key"
- ],
- "frozen": false,
- "output_types": [
- "Tool"
- ],
- "outputs": [
- {
- "cache": true,
- "display_name": "Tool",
- "hidden": null,
- "method": null,
- "name": "tool",
- "selected": "Tool",
- "types": [
- "Tool"
- ],
- "value": "__UNDEFINED__"
- }
- ],
- "pinned": false,
- "template": {
- "_type": "CustomComponent",
- "api_key": {
- "advanced": false,
- "display_name": "API Key",
- "dynamic": false,
- "fileTypes": [],
- "file_path": "",
- "info": "The API key to use SearchApi.",
- "input_types": [
- "Text"
- ],
- "list": false,
- "load_from_db": false,
- "multiline": false,
- "name": "api_key",
- "password": true,
- "placeholder": "",
- "required": true,
- "show": true,
- "title_case": false,
- "type": "str",
- "value": ""
- },
- "code": {
- "advanced": true,
- "dynamic": true,
- "fileTypes": [],
- "file_path": "",
- "info": "",
- "list": false,
- "load_from_db": false,
- "multiline": true,
- "name": "code",
- "password": false,
- "placeholder": "",
- "required": true,
- "show": true,
- "title_case": false,
- "type": "code",
- "value": "from langchain_community.tools.searchapi import SearchAPIRun\nfrom langchain_community.utilities.searchapi import SearchApiAPIWrapper\n\nfrom langflow.custom import CustomComponent\nfrom langflow.field_typing import Tool\n\n\nclass SearchApiToolComponent(CustomComponent):\n display_name: str = \"SearchApi Tool\"\n description: str = \"Real-time search engine results API.\"\n name = \"SearchAPITool\"\n documentation: str = \"https://www.searchapi.io/docs/google\"\n field_config = {\n \"engine\": {\n \"display_name\": \"Engine\",\n \"field_type\": \"str\",\n \"info\": \"The search engine to use.\",\n },\n \"api_key\": {\n \"display_name\": \"API Key\",\n \"field_type\": \"str\",\n \"required\": True,\n \"password\": True,\n \"info\": \"The API key to use SearchApi.\",\n },\n }\n\n def build(\n self,\n engine: str,\n api_key: str,\n ) -> Tool:\n search_api_wrapper = SearchApiAPIWrapper(engine=engine, searchapi_api_key=api_key)\n\n tool = SearchAPIRun(api_wrapper=search_api_wrapper)\n\n self.status = tool\n return tool # type: ignore\n"
- },
- "engine": {
- "advanced": false,
- "display_name": "Engine",
- "dynamic": false,
- "fileTypes": [],
- "file_path": "",
- "info": "The search engine to use.",
- "input_types": [
- "Text"
- ],
- "list": false,
- "load_from_db": false,
- "multiline": false,
- "name": "engine",
- "password": false,
- "placeholder": "",
- "required": true,
- "show": true,
- "title_case": false,
- "type": "str",
- "value": "google"
- }
- }
- },
- "type": "SearchAPITool"
- },
- "dragging": false,
- "height": 403,
- "id": "SearchAPITool-fmETj",
- "position": {
- "x": -1200.258747181863,
- "y": 206.70950310719434
- },
- "positionAbsolute": {
- "x": -1200.258747181863,
- "y": 206.70950310719434
- },
- "selected": false,
- "type": "genericNode",
- "width": 384
+ "width": 432
},
{
"data": {
"description": "Represents an agent of CrewAI.",
"display_name": "CrewAI Agent",
- "id": "CrewAIAgentComponent-V2kfR",
+ "id": "CrewAIAgentComponent-UMpxO",
"node": {
"base_classes": [
"Agent"
@@ -2681,8 +2567,8 @@
"type": "CrewAIAgentComponent"
},
"dragging": false,
- "height": 665,
- "id": "CrewAIAgentComponent-V2kfR",
+ "height": 746,
+ "id": "CrewAIAgentComponent-UMpxO",
"position": {
"x": -397.2627184897183,
"y": 892.6280687419107
@@ -2693,19 +2579,178 @@
},
"selected": false,
"type": "genericNode",
- "width": 384
+ "width": 432
+ },
+ {
+ "data": {
+ "id": "SearchAPI-Yokat",
+ "node": {
+ "base_classes": [
+ "Data",
+ "Tool"
+ ],
+ "beta": false,
+ "conditional_paths": [],
+ "custom_fields": {},
+ "description": "Call the searchapi.io API",
+ "display_name": "Search API",
+ "documentation": "https://www.searchapi.io/docs/google",
+ "edited": false,
+ "field_order": [
+ "engine",
+ "api_key",
+ "input_value",
+ "search_params"
+ ],
+ "frozen": false,
+ "output_types": [],
+ "outputs": [
+ {
+ "cache": true,
+ "display_name": "Data",
+ "method": "run_model",
+ "name": "api_run_model",
+ "selected": "Data",
+ "types": [
+ "Data"
+ ],
+ "value": "__UNDEFINED__"
+ },
+ {
+ "cache": true,
+ "display_name": "Tool",
+ "method": "build_tool",
+ "name": "api_build_tool",
+ "selected": "Tool",
+ "types": [
+ "Tool"
+ ],
+ "value": "__UNDEFINED__"
+ }
+ ],
+ "pinned": false,
+ "template": {
+ "_type": "Component",
+ "api_key": {
+ "advanced": false,
+ "display_name": "SearchAPI API Key",
+ "dynamic": false,
+ "info": "",
+ "input_types": [],
+ "load_from_db": false,
+ "name": "api_key",
+ "password": true,
+ "placeholder": "",
+ "required": true,
+ "show": true,
+ "title_case": false,
+ "type": "str",
+ "value": ""
+ },
+ "code": {
+ "advanced": true,
+ "dynamic": true,
+ "fileTypes": [],
+ "file_path": "",
+ "info": "",
+ "list": false,
+ "load_from_db": false,
+ "multiline": true,
+ "name": "code",
+ "password": false,
+ "placeholder": "",
+ "required": true,
+ "show": true,
+ "title_case": false,
+ "type": "code",
+ "value": "from typing import Union\n\nfrom langchain_community.utilities.searchapi import SearchApiAPIWrapper\n\nfrom langflow.base.langchain_utilities.model import LCToolComponent\nfrom langflow.inputs import SecretStrInput, MultilineInput, DictInput, MessageTextInput\nfrom langflow.schema import Data\nfrom langflow.field_typing import Tool\n\n\nclass SearchAPIComponent(LCToolComponent):\n display_name: str = \"Search API\"\n description: str = \"Call the searchapi.io API\"\n name = \"SearchAPI\"\n documentation: str = \"https://www.searchapi.io/docs/google\"\n\n inputs = [\n MessageTextInput(name=\"engine\", display_name=\"Engine\", value=\"google\"),\n SecretStrInput(name=\"api_key\", display_name=\"SearchAPI API Key\", required=True),\n MultilineInput(\n name=\"input_value\",\n display_name=\"Input\",\n ),\n DictInput(name=\"search_params\", display_name=\"Search parameters\", advanced=True, is_list=True),\n ]\n\n def run_model(self) -> Union[Data, list[Data]]:\n wrapper = self._build_wrapper()\n results = wrapper.results(query=self.input_value, **(self.search_params or {}))\n list_results = results.get(\"organic_results\", [])\n data = [Data(data=result, text=result[\"snippet\"]) for result in list_results]\n self.status = data\n return data\n\n def build_tool(self) -> Tool:\n wrapper = self._build_wrapper()\n return Tool(\n name=\"search_api\",\n description=\"Search for recent results.\",\n func=lambda x: wrapper.run(query=x, **(self.search_params or {})),\n )\n\n def _build_wrapper(self):\n return SearchApiAPIWrapper(engine=self.engine, searchapi_api_key=self.api_key)\n"
+ },
+ "engine": {
+ "advanced": false,
+ "display_name": "Engine",
+ "dynamic": false,
+ "info": "",
+ "input_types": [
+ "Message"
+ ],
+ "list": false,
+ "load_from_db": false,
+ "name": "engine",
+ "placeholder": "",
+ "required": false,
+ "show": true,
+ "title_case": false,
+ "trace_as_input": true,
+ "trace_as_metadata": true,
+ "type": "str",
+ "value": "google"
+ },
+ "input_value": {
+ "advanced": false,
+ "display_name": "Input",
+ "dynamic": false,
+ "info": "",
+ "input_types": [
+ "Message"
+ ],
+ "list": false,
+ "load_from_db": false,
+ "multiline": true,
+ "name": "input_value",
+ "placeholder": "",
+ "required": false,
+ "show": true,
+ "title_case": false,
+ "trace_as_input": true,
+ "trace_as_metadata": true,
+ "type": "str",
+ "value": ""
+ },
+ "search_params": {
+ "advanced": true,
+ "display_name": "Search parameters",
+ "dynamic": false,
+ "info": "",
+ "list": true,
+ "name": "search_params",
+ "placeholder": "",
+ "required": false,
+ "show": true,
+ "title_case": false,
+ "trace_as_input": true,
+ "type": "dict",
+ "value": {}
+ }
+ }
+ },
+ "type": "SearchAPI"
+ },
+ "dragging": false,
+ "height": 612,
+ "id": "SearchAPI-Yokat",
+ "position": {
+ "x": -1229.2392382339021,
+ "y": 59.93107827969652
+ },
+ "positionAbsolute": {
+ "x": -1229.2392382339021,
+ "y": 59.93107827969652
+ },
+ "selected": false,
+ "type": "genericNode",
+ "width": 432
}
],
"viewport": {
- "x": 689.9423538038659,
- "y": 249.5990980882735,
- "zoom": 0.28087497575792186
+ "x": 538.2178429916559,
+ "y": 231.5938714083456,
+ "zoom": 0.25005698994252296
}
},
"description": "This Agentic Flow has a Manager and a couple Workers. The manager can answer the user's question straightaway or delegate the task to other agents.",
"endpoint_name": null,
"id": "6302081f-5af2-4b9f-bd19-2baaf7218ba6",
"is_component": false,
- "last_tested_version": "1.0.9",
+ "last_tested_version": "1.0.12",
"name": "Hierarchical Tasks Agent"
}
\ No newline at end of file
diff --git a/src/frontend/playwright.config.ts b/src/frontend/playwright.config.ts
index 54153792d..6453ee504 100644
--- a/src/frontend/playwright.config.ts
+++ b/src/frontend/playwright.config.ts
@@ -23,7 +23,7 @@ export default defineConfig({
/* Opt out of parallel tests on CI. */
workers: 2,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
- timeout: 120 * 1000,
+ timeout: 3 * 60 * 1000,
// reporter: [
// ["html", { open: "never", outputFolder: "playwright-report/test-results" }],
// ],
diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatMessage/index.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatMessage/index.tsx
index 0638e3c38..458d19e6b 100644
--- a/src/frontend/src/modals/IOModal/components/chatView/chatMessage/index.tsx
+++ b/src/frontend/src/modals/IOModal/components/chatView/chatMessage/index.tsx
@@ -173,7 +173,10 @@ export default function ChatMessage({
)}
{chat.thought && chat.thought !== "" && !hidden &&
}