From a107aa7a773a1176ea0ac9fd81e9a4ebb0a86227 Mon Sep 17 00:00:00 2001 From: Henry Heng Date: Thu, 19 Jun 2025 18:11:24 +0100 Subject: [PATCH] Chore/Update issue templates and add new tools (#4687) * Enhancement: Update issue templates and add new tools - Updated bug report template to include a default label of 'bug'. - Updated feature request template to include a default label of 'enhancement'. - Added new credential class for Agentflow API. - Enhanced Agent and HTTP nodes to improve tool management and error handling. - Added deprecation badges to several agent and chain classes. - Introduced new tools for handling requests (GET, POST, DELETE, PUT) with improved error handling. - Added new chatflows and agentflows for various use cases, including document QnA and translation. - Updated UI components for better handling of agent flows and marketplace interactions. - Refactored utility functions for improved functionality and clarity. * Refactor: Remove beta badge and streamline template title assignment - Removed the 'BETA' badge from the ExtractMetadataRetriever class. - Simplified the title assignment in the agentflowv2 generator by using a variable instead of inline string manipulation. --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- .../credentials/AgentflowApi.credential.ts | 23 + .../components/nodes/agentflow/Agent/Agent.ts | 34 +- .../components/nodes/agentflow/HTTP/HTTP.ts | 7 +- .../components/nodes/agentflow/LLM/LLM.ts | 24 +- .../nodes/agents/AutoGPT/AutoGPT.ts | 2 + .../nodes/agents/BabyAGI/BabyAGI.ts | 2 + .../nodes/chains/ApiChain/GETApiChain.ts | 2 + .../nodes/chains/ApiChain/OpenAPIChain.ts | 2 + .../nodes/chains/ApiChain/POSTApiChain.ts | 2 + .../MultiPromptChain/MultiPromptChain.ts | 2 + .../MultiRetrievalQAChain.ts | 2 + .../RetrievalQAChain/RetrievalQAChain.ts | 2 + .../chains/VectorDBQAChain/VectorDBQAChain.ts | 2 + .../ExtractMetadataRetriever.ts | 1 - .../nodes/tools/AgentAsTool/AgentAsTool.ts | 381 +++ .../nodes/tools/AgentAsTool/agentastool.svg | 1 + .../components/nodes/tools/Arxiv/Arxiv.ts | 144 ++ .../components/nodes/tools/Arxiv/arxiv.png | Bin 0 -> 56182 bytes packages/components/nodes/tools/Arxiv/core.ts | 266 +++ .../nodes/tools/ChatflowTool/ChatflowTool.ts | 20 +- .../tools/OpenAPIToolkit/OpenAPIToolkit.ts | 5 +- .../tools/RequestsDelete/RequestsDelete.ts | 141 ++ .../nodes/tools/RequestsDelete/core.ts | 184 ++ .../nodes/tools/RequestsDelete/del.png | Bin 0 -> 10176 bytes .../nodes/tools/RequestsGet/RequestsGet.ts | 101 +- .../nodes/tools/RequestsGet/core.ts | 171 +- .../nodes/tools/RequestsGet/get.png | Bin 0 -> 7665 bytes .../nodes/tools/RequestsGet/requestsget.svg | 6 - .../nodes/tools/RequestsPost/RequestsPost.ts | 117 +- .../nodes/tools/RequestsPost/core.ts | 123 +- .../nodes/tools/RequestsPost/post.png | Bin 0 -> 11341 bytes .../nodes/tools/RequestsPost/requestspost.svg | 7 - .../nodes/tools/RequestsPut/RequestsPut.ts | 155 ++ .../nodes/tools/RequestsPut/core.ts | 145 ++ .../nodes/tools/RequestsPut/put.png | Bin 0 -> 9839 bytes .../nodes/tools/StripeTool/stripe.png | Bin 69452 -> 9300 bytes packages/components/src/storageUtils.ts | 10 +- packages/components/src/utils.ts | 9 + .../{Agentic RAG V2.json => Agentic RAG.json} | 2 +- ...search With Multi-turn Conversations.json} | 134 +- .../Deep Research With Subagents.json | 1831 +++++++++++++++ ...arch Agent.json => Human In The Loop.json} | 1313 +++++------ .../agentflowsv2/Interacting With API.json | 1294 +++++++++++ .../marketplaces/agentflowsv2/SQL Agent.json | 2052 +++++++++++++++++ ... Reply HITL Agent.json => Simple RAG.json} | 340 +-- .../agentflowsv2/Structured Output.json | 549 +++++ .../agentflowsv2/Supervisor Worker.json | 118 +- .../marketplaces/agentflowsv2/Translator.json | 544 +++++ .../{Slack Agent.json => Workplace Chat.json} | 188 +- .../marketplaces/chatflows/Antonym.json | 533 ----- .../chatflows/Context Chat Engine.json | 1 - .../chatflows/Conversation Chain.json | 3 +- .../Conversational Retrieval QA Chain.json | 1 - ...ise Docs QnA.json => Github Docs QnA.json} | 3 +- .../server/marketplaces/chatflows/IfElse.json | 1246 ---------- .../marketplaces/chatflows/Local QnA.json | 1 - .../chatflows/Multi Prompt Chain.json | 499 ---- .../chatflows/Multi Retrieval QA Chain.json | 1222 ---------- .../chatflows/Multiple Documents QnA.json | 1 - .../chatflows/Multiple VectorDB.json | 1916 --------------- ...API Agent.json => OpenAPI YAML Agent.json} | 2 +- .../Prompt Chaining with VectorStore.json | 1277 ---------- .../marketplaces/chatflows/SQL Prompt.json | 1983 ---------------- .../chatflows/Simple Chat Engine.json | 2 +- .../chatflows/Structured Output Parser.json | 490 ---- .../marketplaces/chatflows/Tool Agent.json | 631 +++++ .../chatflows/Transcript Summarization.json | 512 ---- .../marketplaces/chatflows/Translator.json | 424 ---- .../chatflows/Vectara RAG Chain.json | 398 ---- .../marketplaces/chatflows/WebPage QnA.json | 788 ------- .../services/agentflowv2-generator/index.ts | 9 +- .../src/services/documentstore/index.ts | 8 +- .../server/src/services/marketplaces/index.ts | 27 +- packages/server/src/utils/buildAgentflow.ts | 37 +- packages/server/src/utils/index.ts | 1 + packages/server/src/utils/logger.ts | 10 +- .../src/ui-component/button/FlowListMenu.jsx | 4 +- .../ui/src/ui-component/input/RichInput.jsx | 20 +- .../ui-component/input/suggestionOption.js | 6 + .../ui/src/ui-component/markdown/Markdown.css | 42 + .../src/ui-component/table/FlowListTable.jsx | 2 +- .../ui-component/table/MarketplaceTable.jsx | 8 +- .../ui/src/views/canvas/NodeInputHandler.jsx | 5 +- packages/ui/src/views/marketplaces/index.jsx | 2 +- 86 files changed, 9942 insertions(+), 12634 deletions(-) create mode 100644 packages/components/credentials/AgentflowApi.credential.ts create mode 100644 packages/components/nodes/tools/AgentAsTool/AgentAsTool.ts create mode 100644 packages/components/nodes/tools/AgentAsTool/agentastool.svg create mode 100644 packages/components/nodes/tools/Arxiv/Arxiv.ts create mode 100644 packages/components/nodes/tools/Arxiv/arxiv.png create mode 100644 packages/components/nodes/tools/Arxiv/core.ts create mode 100644 packages/components/nodes/tools/RequestsDelete/RequestsDelete.ts create mode 100644 packages/components/nodes/tools/RequestsDelete/core.ts create mode 100644 packages/components/nodes/tools/RequestsDelete/del.png create mode 100644 packages/components/nodes/tools/RequestsGet/get.png delete mode 100644 packages/components/nodes/tools/RequestsGet/requestsget.svg create mode 100644 packages/components/nodes/tools/RequestsPost/post.png delete mode 100644 packages/components/nodes/tools/RequestsPost/requestspost.svg create mode 100644 packages/components/nodes/tools/RequestsPut/RequestsPut.ts create mode 100644 packages/components/nodes/tools/RequestsPut/core.ts create mode 100644 packages/components/nodes/tools/RequestsPut/put.png rename packages/server/marketplaces/agentflowsv2/{Agentic RAG V2.json => Agentic RAG.json} (99%) rename packages/server/marketplaces/agentflowsv2/{Deep Research V2.json => Deep Research With Multi-turn Conversations.json} (98%) create mode 100644 packages/server/marketplaces/agentflowsv2/Deep Research With Subagents.json rename packages/server/marketplaces/agentflowsv2/{Financial Research Agent.json => Human In The Loop.json} (67%) create mode 100644 packages/server/marketplaces/agentflowsv2/Interacting With API.json create mode 100644 packages/server/marketplaces/agentflowsv2/SQL Agent.json rename packages/server/marketplaces/agentflowsv2/{Email Reply HITL Agent.json => Simple RAG.json} (66%) create mode 100644 packages/server/marketplaces/agentflowsv2/Structured Output.json create mode 100644 packages/server/marketplaces/agentflowsv2/Translator.json rename packages/server/marketplaces/agentflowsv2/{Slack Agent.json => Workplace Chat.json} (81%) delete mode 100644 packages/server/marketplaces/chatflows/Antonym.json rename packages/server/marketplaces/chatflows/{Flowise Docs QnA.json => Github Docs QnA.json} (99%) delete mode 100644 packages/server/marketplaces/chatflows/IfElse.json delete mode 100644 packages/server/marketplaces/chatflows/Multi Prompt Chain.json delete mode 100644 packages/server/marketplaces/chatflows/Multi Retrieval QA Chain.json delete mode 100644 packages/server/marketplaces/chatflows/Multiple VectorDB.json rename packages/server/marketplaces/chatflows/{API Agent.json => OpenAPI YAML Agent.json} (99%) delete mode 100644 packages/server/marketplaces/chatflows/Prompt Chaining with VectorStore.json delete mode 100644 packages/server/marketplaces/chatflows/SQL Prompt.json delete mode 100644 packages/server/marketplaces/chatflows/Structured Output Parser.json create mode 100644 packages/server/marketplaces/chatflows/Tool Agent.json delete mode 100644 packages/server/marketplaces/chatflows/Transcript Summarization.json delete mode 100644 packages/server/marketplaces/chatflows/Translator.json delete mode 100644 packages/server/marketplaces/chatflows/Vectara RAG Chain.json delete mode 100644 packages/server/marketplaces/chatflows/WebPage QnA.json diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 00a3c52d..b912e751 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,7 +2,7 @@ name: Bug report about: Create a report to help us improve title: '[BUG]' -labels: '' +labels: bug assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 557a358e..adb350cd 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: Feature request about: Suggest an idea for this project title: '[FEATURE]' -labels: '' +labels: enhancement assignees: '' --- diff --git a/packages/components/credentials/AgentflowApi.credential.ts b/packages/components/credentials/AgentflowApi.credential.ts new file mode 100644 index 00000000..72f4cefe --- /dev/null +++ b/packages/components/credentials/AgentflowApi.credential.ts @@ -0,0 +1,23 @@ +import { INodeParams, INodeCredential } from '../src/Interface' + +class AgentflowApi implements INodeCredential { + label: string + name: string + version: number + inputs: INodeParams[] + + constructor() { + this.label = 'Agentflow API' + this.name = 'agentflowApi' + this.version = 1.0 + this.inputs = [ + { + label: 'Agentflow Api Key', + name: 'agentflowApiKey', + type: 'password' + } + ] + } +} + +module.exports = { credClass: AgentflowApi } diff --git a/packages/components/nodes/agentflow/Agent/Agent.ts b/packages/components/nodes/agentflow/Agent/Agent.ts index fd227735..8e364f8d 100644 --- a/packages/components/nodes/agentflow/Agent/Agent.ts +++ b/packages/components/nodes/agentflow/Agent/Agent.ts @@ -496,18 +496,21 @@ class Agent_Agentflow implements INode { } } const toolInstance = await newToolNodeInstance.init(newNodeData, '', options) - if (tool.agentSelectedToolRequiresHumanInput) { - toolInstance.requiresHumanInput = true - } // toolInstance might returns a list of tools like MCP tools if (Array.isArray(toolInstance)) { for (const subTool of toolInstance) { const subToolInstance = subTool as Tool ;(subToolInstance as any).agentSelectedTool = tool.agentSelectedTool + if (tool.agentSelectedToolRequiresHumanInput) { + ;(subToolInstance as any).requiresHumanInput = true + } toolsInstance.push(subToolInstance) } } else { + if (tool.agentSelectedToolRequiresHumanInput) { + toolInstance.requiresHumanInput = true + } toolsInstance.push(toolInstance as Tool) } } @@ -929,7 +932,14 @@ class Agent_Agentflow implements INode { } // Prepare final response and output object - const finalResponse = (response.content as string) ?? JSON.stringify(response, null, 2) + let finalResponse = '' + if (response.content && Array.isArray(response.content)) { + finalResponse = response.content.map((item: any) => item.text).join('\n') + } else if (response.content && typeof response.content === 'string') { + finalResponse = response.content + } else { + finalResponse = JSON.stringify(response, null, 2) + } const output = this.prepareOutputObject( response, availableTools, @@ -1374,6 +1384,7 @@ class Agent_Agentflow implements INode { const usedTools: IUsedTool[] = [] let sourceDocuments: Array = [] let artifacts: any[] = [] + let isWaitingForHumanInput: boolean | undefined // Process each tool call for (let i = 0; i < response.tool_calls.length; i++) { @@ -1536,7 +1547,8 @@ class Agent_Agentflow implements INode { usedTools: recursiveUsedTools, sourceDocuments: recursiveSourceDocuments, artifacts: recursiveArtifacts, - totalTokens: recursiveTokens + totalTokens: recursiveTokens, + isWaitingForHumanInput: recursiveIsWaitingForHumanInput } = await this.handleToolCalls({ response: newResponse, messages, @@ -1558,9 +1570,10 @@ class Agent_Agentflow implements INode { sourceDocuments = [...sourceDocuments, ...recursiveSourceDocuments] artifacts = [...artifacts, ...recursiveArtifacts] totalTokens += recursiveTokens + isWaitingForHumanInput = recursiveIsWaitingForHumanInput } - return { response: newResponse, usedTools, sourceDocuments, artifacts, totalTokens } + return { response: newResponse, usedTools, sourceDocuments, artifacts, totalTokens, isWaitingForHumanInput } } /** @@ -1660,7 +1673,14 @@ class Agent_Agentflow implements INode { if (humanInput.type === 'reject') { messages.pop() - toolsInstance = toolsInstance.filter((tool) => tool.name !== toolCall.name) + const toBeRemovedTool = toolsInstance.find((tool) => tool.name === toolCall.name) + if (toBeRemovedTool) { + toolsInstance = toolsInstance.filter((tool) => tool.name !== toolCall.name) + // Remove other tools with the same agentSelectedTool such as MCP tools + toolsInstance = toolsInstance.filter( + (tool) => (tool as any).agentSelectedTool !== (toBeRemovedTool as any).agentSelectedTool + ) + } } if (humanInput.type === 'proceed') { let toolIds: ICommonObject | undefined diff --git a/packages/components/nodes/agentflow/HTTP/HTTP.ts b/packages/components/nodes/agentflow/HTTP/HTTP.ts index 0027f1e2..9c323405 100644 --- a/packages/components/nodes/agentflow/HTTP/HTTP.ts +++ b/packages/components/nodes/agentflow/HTTP/HTTP.ts @@ -336,6 +336,9 @@ class HTTP_Agentflow implements INode { } catch (error) { console.error('HTTP Request Error:', error) + const errorMessage = + error.response?.data?.message || error.response?.data?.error || error.message || 'An error occurred during the HTTP request' + // Format error response const errorResponse: any = { id: nodeData.id, @@ -353,7 +356,7 @@ class HTTP_Agentflow implements INode { }, error: { name: error.name || 'Error', - message: error.message || 'An error occurred during the HTTP request' + message: errorMessage }, state } @@ -366,7 +369,7 @@ class HTTP_Agentflow implements INode { errorResponse.error.headers = error.response.headers } - throw new Error(error) + throw new Error(errorMessage) } } } diff --git a/packages/components/nodes/agentflow/LLM/LLM.ts b/packages/components/nodes/agentflow/LLM/LLM.ts index 8b400e7e..5e881e1b 100644 --- a/packages/components/nodes/agentflow/LLM/LLM.ts +++ b/packages/components/nodes/agentflow/LLM/LLM.ts @@ -262,6 +262,7 @@ class LLM_Agentflow implements INode { }`, description: 'JSON schema for the structured output', optional: true, + hideCodeExecute: true, show: { 'llmStructuredOutput[$index].type': 'jsonArray' } @@ -486,8 +487,15 @@ class LLM_Agentflow implements INode { } // Prepare final response and output object - const finalResponse = (response.content as string) ?? JSON.stringify(response, null, 2) - const output = this.prepareOutputObject(response, finalResponse, startTime, endTime, timeDelta) + let finalResponse = '' + if (response.content && Array.isArray(response.content)) { + finalResponse = response.content.map((item: any) => item.text).join('\n') + } else if (response.content && typeof response.content === 'string') { + finalResponse = response.content + } else { + finalResponse = JSON.stringify(response, null, 2) + } + const output = this.prepareOutputObject(response, finalResponse, startTime, endTime, timeDelta, isStructuredOutput) // End analytics tracking if (analyticHandlers && llmIds) { @@ -853,7 +861,8 @@ class LLM_Agentflow implements INode { finalResponse: string, startTime: number, endTime: number, - timeDelta: number + timeDelta: number, + isStructuredOutput: boolean ): any { const output: any = { content: finalResponse, @@ -872,6 +881,15 @@ class LLM_Agentflow implements INode { output.usageMetadata = response.usage_metadata } + if (isStructuredOutput && typeof response === 'object') { + const structuredOutput = response as Record + for (const key in structuredOutput) { + if (structuredOutput[key]) { + output[key] = structuredOutput[key] + } + } + } + return output } diff --git a/packages/components/nodes/agents/AutoGPT/AutoGPT.ts b/packages/components/nodes/agents/AutoGPT/AutoGPT.ts index c41a5296..04fd8e92 100644 --- a/packages/components/nodes/agents/AutoGPT/AutoGPT.ts +++ b/packages/components/nodes/agents/AutoGPT/AutoGPT.ts @@ -23,6 +23,7 @@ class AutoGPT_Agents implements INode { category: string baseClasses: string[] inputs: INodeParams[] + badge: string constructor() { this.label = 'AutoGPT' @@ -30,6 +31,7 @@ class AutoGPT_Agents implements INode { this.version = 2.0 this.type = 'AutoGPT' this.category = 'Agents' + this.badge = 'DEPRECATING' this.icon = 'autogpt.svg' this.description = 'Autonomous agent with chain of thoughts for self-guided task completion' this.baseClasses = ['AutoGPT'] diff --git a/packages/components/nodes/agents/BabyAGI/BabyAGI.ts b/packages/components/nodes/agents/BabyAGI/BabyAGI.ts index 87d5cd28..d3bad903 100644 --- a/packages/components/nodes/agents/BabyAGI/BabyAGI.ts +++ b/packages/components/nodes/agents/BabyAGI/BabyAGI.ts @@ -15,6 +15,7 @@ class BabyAGI_Agents implements INode { category: string baseClasses: string[] inputs: INodeParams[] + badge: string constructor() { this.label = 'BabyAGI' @@ -23,6 +24,7 @@ class BabyAGI_Agents implements INode { this.type = 'BabyAGI' this.category = 'Agents' this.icon = 'babyagi.svg' + this.badge = 'DEPRECATING' this.description = 'Task Driven Autonomous Agent which creates new task and reprioritizes task list based on objective' this.baseClasses = ['BabyAGI'] this.inputs = [ diff --git a/packages/components/nodes/chains/ApiChain/GETApiChain.ts b/packages/components/nodes/chains/ApiChain/GETApiChain.ts index ba9ac40a..ca97e755 100644 --- a/packages/components/nodes/chains/ApiChain/GETApiChain.ts +++ b/packages/components/nodes/chains/ApiChain/GETApiChain.ts @@ -26,6 +26,7 @@ class GETApiChain_Chains implements INode { baseClasses: string[] description: string inputs: INodeParams[] + badge: string constructor() { this.label = 'GET API Chain' @@ -34,6 +35,7 @@ class GETApiChain_Chains implements INode { this.type = 'GETApiChain' this.icon = 'get.svg' this.category = 'Chains' + this.badge = 'DEPRECATING' this.description = 'Chain to run queries against GET API' this.baseClasses = [this.type, ...getBaseClasses(APIChain)] this.inputs = [ diff --git a/packages/components/nodes/chains/ApiChain/OpenAPIChain.ts b/packages/components/nodes/chains/ApiChain/OpenAPIChain.ts index 91c1c149..48cfd5d0 100644 --- a/packages/components/nodes/chains/ApiChain/OpenAPIChain.ts +++ b/packages/components/nodes/chains/ApiChain/OpenAPIChain.ts @@ -17,6 +17,7 @@ class OpenApiChain_Chains implements INode { baseClasses: string[] description: string inputs: INodeParams[] + badge: string constructor() { this.label = 'OpenAPI Chain' @@ -25,6 +26,7 @@ class OpenApiChain_Chains implements INode { this.type = 'OpenAPIChain' this.icon = 'openapi.svg' this.category = 'Chains' + this.badge = 'DEPRECATING' this.description = 'Chain that automatically select and call APIs based only on an OpenAPI spec' this.baseClasses = [this.type, ...getBaseClasses(APIChain)] this.inputs = [ diff --git a/packages/components/nodes/chains/ApiChain/POSTApiChain.ts b/packages/components/nodes/chains/ApiChain/POSTApiChain.ts index 20e5447b..b9a489c4 100644 --- a/packages/components/nodes/chains/ApiChain/POSTApiChain.ts +++ b/packages/components/nodes/chains/ApiChain/POSTApiChain.ts @@ -15,6 +15,7 @@ class POSTApiChain_Chains implements INode { baseClasses: string[] description: string inputs: INodeParams[] + badge: string constructor() { this.label = 'POST API Chain' @@ -23,6 +24,7 @@ class POSTApiChain_Chains implements INode { this.type = 'POSTApiChain' this.icon = 'post.svg' this.category = 'Chains' + this.badge = 'DEPRECATING' this.description = 'Chain to run queries against POST API' this.baseClasses = [this.type, ...getBaseClasses(APIChain)] this.inputs = [ diff --git a/packages/components/nodes/chains/MultiPromptChain/MultiPromptChain.ts b/packages/components/nodes/chains/MultiPromptChain/MultiPromptChain.ts index a2fae0db..da683400 100644 --- a/packages/components/nodes/chains/MultiPromptChain/MultiPromptChain.ts +++ b/packages/components/nodes/chains/MultiPromptChain/MultiPromptChain.ts @@ -16,11 +16,13 @@ class MultiPromptChain_Chains implements INode { baseClasses: string[] description: string inputs: INodeParams[] + badge: string constructor() { this.label = 'Multi Prompt Chain' this.name = 'multiPromptChain' this.version = 2.0 + this.badge = 'DEPRECATING' this.type = 'MultiPromptChain' this.icon = 'prompt.svg' this.category = 'Chains' diff --git a/packages/components/nodes/chains/MultiRetrievalQAChain/MultiRetrievalQAChain.ts b/packages/components/nodes/chains/MultiRetrievalQAChain/MultiRetrievalQAChain.ts index b0c90bad..bdcd3762 100644 --- a/packages/components/nodes/chains/MultiRetrievalQAChain/MultiRetrievalQAChain.ts +++ b/packages/components/nodes/chains/MultiRetrievalQAChain/MultiRetrievalQAChain.ts @@ -15,12 +15,14 @@ class MultiRetrievalQAChain_Chains implements INode { category: string baseClasses: string[] description: string + badge: string inputs: INodeParams[] constructor() { this.label = 'Multi Retrieval QA Chain' this.name = 'multiRetrievalQAChain' this.version = 2.0 + this.badge = 'DEPRECATING' this.type = 'MultiRetrievalQAChain' this.icon = 'qa.svg' this.category = 'Chains' diff --git a/packages/components/nodes/chains/RetrievalQAChain/RetrievalQAChain.ts b/packages/components/nodes/chains/RetrievalQAChain/RetrievalQAChain.ts index ae023862..f82d92e0 100644 --- a/packages/components/nodes/chains/RetrievalQAChain/RetrievalQAChain.ts +++ b/packages/components/nodes/chains/RetrievalQAChain/RetrievalQAChain.ts @@ -17,6 +17,7 @@ class RetrievalQAChain_Chains implements INode { baseClasses: string[] description: string inputs: INodeParams[] + badge: string constructor() { this.label = 'Retrieval QA Chain' @@ -24,6 +25,7 @@ class RetrievalQAChain_Chains implements INode { this.version = 2.0 this.type = 'RetrievalQAChain' this.icon = 'qa.svg' + this.badge = 'DEPRECATING' this.category = 'Chains' this.description = 'QA chain to answer a question based on the retrieved documents' this.baseClasses = [this.type, ...getBaseClasses(RetrievalQAChain)] diff --git a/packages/components/nodes/chains/VectorDBQAChain/VectorDBQAChain.ts b/packages/components/nodes/chains/VectorDBQAChain/VectorDBQAChain.ts index 2fd36919..f111f652 100644 --- a/packages/components/nodes/chains/VectorDBQAChain/VectorDBQAChain.ts +++ b/packages/components/nodes/chains/VectorDBQAChain/VectorDBQAChain.ts @@ -17,6 +17,7 @@ class VectorDBQAChain_Chains implements INode { baseClasses: string[] description: string inputs: INodeParams[] + badge: string constructor() { this.label = 'VectorDB QA Chain' @@ -25,6 +26,7 @@ class VectorDBQAChain_Chains implements INode { this.type = 'VectorDBQAChain' this.icon = 'vectordb.svg' this.category = 'Chains' + this.badge = 'DEPRECATING' this.description = 'QA chain for vector databases' this.baseClasses = [this.type, ...getBaseClasses(VectorDBQAChain)] this.inputs = [ diff --git a/packages/components/nodes/retrievers/ExtractMetadataRetriever/ExtractMetadataRetriever.ts b/packages/components/nodes/retrievers/ExtractMetadataRetriever/ExtractMetadataRetriever.ts index 48168445..0df1b725 100644 --- a/packages/components/nodes/retrievers/ExtractMetadataRetriever/ExtractMetadataRetriever.ts +++ b/packages/components/nodes/retrievers/ExtractMetadataRetriever/ExtractMetadataRetriever.ts @@ -31,7 +31,6 @@ class ExtractMetadataRetriever_Retrievers implements INode { this.category = 'Retrievers' this.description = 'Extract keywords/metadata from the query and use it to filter documents' this.baseClasses = [this.type, 'BaseRetriever'] - this.badge = 'BETA' this.inputs = [ { label: 'Vector Store', diff --git a/packages/components/nodes/tools/AgentAsTool/AgentAsTool.ts b/packages/components/nodes/tools/AgentAsTool/AgentAsTool.ts new file mode 100644 index 00000000..5f3d7e13 --- /dev/null +++ b/packages/components/nodes/tools/AgentAsTool/AgentAsTool.ts @@ -0,0 +1,381 @@ +import { DataSource } from 'typeorm' +import { z } from 'zod' +import { NodeVM } from '@flowiseai/nodevm' +import { RunnableConfig } from '@langchain/core/runnables' +import { CallbackManagerForToolRun, Callbacks, CallbackManager, parseCallbackConfigArg } from '@langchain/core/callbacks/manager' +import { StructuredTool } from '@langchain/core/tools' +import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../src/Interface' +import { availableDependencies, defaultAllowBuiltInDep, getCredentialData, getCredentialParam } from '../../../src/utils' +import { v4 as uuidv4 } from 'uuid' + +class AgentAsTool_Tools implements INode { + label: string + name: string + version: number + description: string + type: string + icon: string + category: string + baseClasses: string[] + credential: INodeParams + inputs: INodeParams[] + + constructor() { + this.label = 'Agent as Tool' + this.name = 'agentAsTool' + this.version = 1.0 + this.type = 'AgentAsTool' + this.icon = 'agentastool.svg' + this.category = 'Tools' + this.description = 'Use as a tool to execute another agentflow' + this.baseClasses = [this.type, 'Tool'] + this.credential = { + label: 'Connect Credential', + name: 'credential', + type: 'credential', + credentialNames: ['agentflowApi'], + optional: true + } + this.inputs = [ + { + label: 'Select Agent', + name: 'selectedAgentflow', + type: 'asyncOptions', + loadMethod: 'listAgentflows' + }, + { + label: 'Tool Name', + name: 'name', + type: 'string' + }, + { + label: 'Tool Description', + name: 'description', + type: 'string', + description: 'Description of what the tool does. This is for LLM to determine when to use this tool.', + rows: 3, + placeholder: + 'State of the Union QA - useful for when you need to ask questions about the most recent state of the union address.' + }, + { + label: 'Return Direct', + name: 'returnDirect', + type: 'boolean', + optional: true + }, + { + label: 'Override Config', + name: 'overrideConfig', + description: 'Override the config passed to the Agentflow.', + type: 'json', + optional: true, + additionalParams: true + }, + { + label: 'Base URL', + name: 'baseURL', + type: 'string', + description: + 'Base URL to Flowise. By default, it is the URL of the incoming request. Useful when you need to execute the Agentflow through an alternative route.', + placeholder: 'http://localhost:3000', + optional: true, + additionalParams: true + }, + { + label: 'Start new session per message', + name: 'startNewSession', + type: 'boolean', + description: + 'Whether to continue the session with the Agentflow tool or start a new one with each interaction. Useful for Agentflows with memory if you want to avoid it.', + default: false, + optional: true, + additionalParams: true + }, + { + label: 'Use Question from Chat', + name: 'useQuestionFromChat', + type: 'boolean', + description: + 'Whether to use the question from the chat as input to the agentflow. If turned on, this will override the custom input.', + optional: true, + additionalParams: true + }, + { + label: 'Custom Input', + name: 'customInput', + type: 'string', + description: 'Custom input to be passed to the agentflow. Leave empty to let LLM decides the input.', + optional: true, + additionalParams: true, + show: { + useQuestionFromChat: false + } + } + ] + } + + //@ts-ignore + loadMethods = { + async listAgentflows(_: INodeData, options: ICommonObject): Promise { + const returnData: INodeOptionsValue[] = [] + + const appDataSource = options.appDataSource as DataSource + const databaseEntities = options.databaseEntities as IDatabaseEntity + if (appDataSource === undefined || !appDataSource) { + return returnData + } + + const searchOptions = options.searchOptions || {} + const agentflows = await appDataSource.getRepository(databaseEntities['ChatFlow']).findBy({ + ...searchOptions, + type: 'AGENTFLOW' + }) + + for (let i = 0; i < agentflows.length; i += 1) { + const data = { + label: agentflows[i].name, + name: agentflows[i].id + } as INodeOptionsValue + returnData.push(data) + } + return returnData + } + } + + async init(nodeData: INodeData, input: string, options: ICommonObject): Promise { + const selectedAgentflowId = nodeData.inputs?.selectedAgentflow as string + const _name = nodeData.inputs?.name as string + const description = nodeData.inputs?.description as string + const useQuestionFromChat = nodeData.inputs?.useQuestionFromChat as boolean + const returnDirect = nodeData.inputs?.returnDirect as boolean + const customInput = nodeData.inputs?.customInput as string + const overrideConfig = + typeof nodeData.inputs?.overrideConfig === 'string' && + nodeData.inputs.overrideConfig.startsWith('{') && + nodeData.inputs.overrideConfig.endsWith('}') + ? JSON.parse(nodeData.inputs.overrideConfig) + : nodeData.inputs?.overrideConfig + + const startNewSession = nodeData.inputs?.startNewSession as boolean + + const baseURL = (nodeData.inputs?.baseURL as string) || (options.baseURL as string) + + const credentialData = await getCredentialData(nodeData.credential ?? '', options) + const agentflowApiKey = getCredentialParam('agentflowApiKey', credentialData, nodeData) + + if (selectedAgentflowId === options.chatflowid) throw new Error('Cannot call the same agentflow!') + + let headers = {} + if (agentflowApiKey) headers = { Authorization: `Bearer ${agentflowApiKey}` } + + let toolInput = '' + if (useQuestionFromChat) { + toolInput = input + } else if (customInput) { + toolInput = customInput + } + + let name = _name || 'agentflow_tool' + + return new AgentflowTool({ + name, + baseURL, + description, + returnDirect, + agentflowid: selectedAgentflowId, + startNewSession, + headers, + input: toolInput, + overrideConfig + }) + } +} + +class AgentflowTool extends StructuredTool { + static lc_name() { + return 'AgentflowTool' + } + + name = 'agentflow_tool' + + description = 'Execute another agentflow' + + input = '' + + agentflowid = '' + + startNewSession = false + + baseURL = 'http://localhost:3000' + + headers = {} + + overrideConfig?: object + + schema = z.object({ + input: z.string().describe('input question') + // overrideConfig: z.record(z.any()).optional().describe('override config'), // This will be passed to the Agent, so comment it for now. + }) as any + + constructor({ + name, + description, + returnDirect, + input, + agentflowid, + startNewSession, + baseURL, + headers, + overrideConfig + }: { + name: string + description: string + returnDirect: boolean + input: string + agentflowid: string + startNewSession: boolean + baseURL: string + headers: ICommonObject + overrideConfig?: object + }) { + super() + this.name = name + this.description = description + this.input = input + this.baseURL = baseURL + this.startNewSession = startNewSession + this.headers = headers + this.agentflowid = agentflowid + this.overrideConfig = overrideConfig + this.returnDirect = returnDirect + } + + async call( + arg: z.infer, + configArg?: RunnableConfig | Callbacks, + tags?: string[], + flowConfig?: { sessionId?: string; chatId?: string; input?: string } + ): Promise { + const config = parseCallbackConfigArg(configArg) + if (config.runName === undefined) { + config.runName = this.name + } + let parsed + try { + parsed = await this.schema.parseAsync(arg) + } catch (e) { + throw new Error(`Received tool input did not match expected schema: ${JSON.stringify(arg)}`) + } + const callbackManager_ = await CallbackManager.configure( + config.callbacks, + this.callbacks, + config.tags || tags, + this.tags, + config.metadata, + this.metadata, + { verbose: this.verbose } + ) + const runManager = await callbackManager_?.handleToolStart( + this.toJSON(), + typeof parsed === 'string' ? parsed : JSON.stringify(parsed), + undefined, + undefined, + undefined, + undefined, + config.runName + ) + let result + try { + result = await this._call(parsed, runManager, flowConfig) + } catch (e) { + await runManager?.handleToolError(e) + throw e + } + if (result && typeof result !== 'string') { + result = JSON.stringify(result) + } + await runManager?.handleToolEnd(result) + return result + } + + // @ts-ignore + protected async _call( + arg: z.infer, + _?: CallbackManagerForToolRun, + flowConfig?: { sessionId?: string; chatId?: string; input?: string } + ): Promise { + const inputQuestion = this.input || arg.input + + const body = { + question: inputQuestion, + chatId: this.startNewSession ? uuidv4() : flowConfig?.chatId, + overrideConfig: { + sessionId: this.startNewSession ? uuidv4() : flowConfig?.sessionId, + ...(this.overrideConfig ?? {}), + ...(arg.overrideConfig ?? {}) + } + } + + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'flowise-tool': 'true', + ...this.headers + }, + body: JSON.stringify(body) + } + + let sandbox = { + $callOptions: options, + $callBody: body, + util: undefined, + Symbol: undefined, + child_process: undefined, + fs: undefined, + process: undefined + } + + const code = ` +const fetch = require('node-fetch'); +const url = "${this.baseURL}/api/v1/prediction/${this.agentflowid}"; + +const body = $callBody; + +const options = $callOptions; + +try { + const response = await fetch(url, options); + const resp = await response.json(); + return resp.text; +} catch (error) { + console.error(error); + return ''; +} +` + const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP + ? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(',')) + : defaultAllowBuiltInDep + const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : [] + const deps = availableDependencies.concat(externalDeps) + + const vmOptions = { + console: 'inherit', + sandbox, + require: { + external: { modules: deps }, + builtin: builtinDeps + }, + eval: false, + wasm: false, + timeout: 10000 + } as any + + const vm = new NodeVM(vmOptions) + const response = await vm.run(`module.exports = async function() {${code}}()`, __dirname) + + return response + } +} + +module.exports = { nodeClass: AgentAsTool_Tools } diff --git a/packages/components/nodes/tools/AgentAsTool/agentastool.svg b/packages/components/nodes/tools/AgentAsTool/agentastool.svg new file mode 100644 index 00000000..cd6cd8de --- /dev/null +++ b/packages/components/nodes/tools/AgentAsTool/agentastool.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/nodes/tools/Arxiv/Arxiv.ts b/packages/components/nodes/tools/Arxiv/Arxiv.ts new file mode 100644 index 00000000..d1fc6222 --- /dev/null +++ b/packages/components/nodes/tools/Arxiv/Arxiv.ts @@ -0,0 +1,144 @@ +import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses } from '../../../src/utils' +import { ArxivParameters, desc, ArxivTool } from './core' + +class Arxiv_Tools implements INode { + label: string + name: string + version: number + description: string + type: string + icon: string + category: string + baseClasses: string[] + inputs: INodeParams[] + + constructor() { + this.label = 'Arxiv' + this.name = 'arxiv' + this.version = 1.0 + this.type = 'Arxiv' + this.icon = 'arxiv.png' + this.category = 'Tools' + this.description = 'Search and read content from academic papers on Arxiv' + this.baseClasses = [this.type, ...getBaseClasses(ArxivTool)] + this.inputs = [ + { + label: 'Name', + name: 'arxivName', + type: 'string', + default: 'arxiv_search', + description: 'Name of the tool', + additionalParams: true, + optional: true + }, + { + label: 'Description', + name: 'arxivDescription', + type: 'string', + rows: 4, + default: desc, + description: 'Describe to LLM when it should use this tool', + additionalParams: true, + optional: true + }, + { + label: 'Top K Results', + name: 'topKResults', + type: 'number', + description: 'Number of top results to return from Arxiv search', + default: '3', + step: 1, + optional: true, + additionalParams: true + }, + { + label: 'Max Query Length', + name: 'maxQueryLength', + type: 'number', + description: 'Maximum length of the search query', + default: '300', + step: 1, + optional: true, + additionalParams: true + }, + { + label: 'Max Content Length', + name: 'docContentCharsMax', + type: 'number', + description: 'Maximum length of the returned content. Set to 0 for unlimited', + default: '10000', + step: 1, + optional: true, + additionalParams: true + }, + { + label: 'Load Full Content', + name: 'loadFullContent', + type: 'boolean', + description: + 'Download PDFs and extract full paper content instead of just summaries. Warning: This is slower and uses more resources.', + default: false, + optional: true, + additionalParams: true + }, + { + label: 'Continue On Failure', + name: 'continueOnFailure', + type: 'boolean', + description: + 'Continue processing other papers if one fails to download/parse (only applies when Load Full Content is enabled)', + default: false, + optional: true, + additionalParams: true + }, + { + label: 'Use Legacy Build', + name: 'legacyBuild', + type: 'boolean', + description: 'Use legacy PDF.js build for PDF parsing (only applies when Load Full Content is enabled)', + default: false, + optional: true, + additionalParams: true + } + ] + } + + async init(nodeData: INodeData, _: string, options: ICommonObject): Promise { + const name = (nodeData.inputs?.name as string) || (nodeData.inputs?.arxivName as string) + const description = (nodeData.inputs?.description as string) || (nodeData.inputs?.arxivDescription as string) + const topKResults = nodeData.inputs?.topKResults as string + const maxQueryLength = nodeData.inputs?.maxQueryLength as string + const docContentCharsMax = nodeData.inputs?.docContentCharsMax as string + const loadFullContent = nodeData.inputs?.loadFullContent as boolean + const continueOnFailure = nodeData.inputs?.continueOnFailure as boolean + const legacyBuild = nodeData.inputs?.legacyBuild as boolean + + let logger + const orgId = options.orgId + if (process.env.DEBUG === 'true') { + logger = options.logger + } + + const obj: ArxivParameters = {} + if (description) obj.description = description + if (name) + obj.name = name + .toLowerCase() + .replace(/ /g, '_') + .replace(/[^a-z0-9_-]/g, '') + if (topKResults) obj.topKResults = parseInt(topKResults, 10) + if (maxQueryLength) obj.maxQueryLength = parseInt(maxQueryLength, 10) + if (docContentCharsMax) { + const maxChars = parseInt(docContentCharsMax, 10) + obj.docContentCharsMax = maxChars === 0 ? undefined : maxChars + } + if (loadFullContent !== undefined) obj.loadFullContent = loadFullContent + if (continueOnFailure !== undefined) obj.continueOnFailure = continueOnFailure + if (legacyBuild !== undefined) obj.legacyBuild = legacyBuild + + return new ArxivTool(obj, logger, orgId) + } +} + +module.exports = { nodeClass: Arxiv_Tools } diff --git a/packages/components/nodes/tools/Arxiv/arxiv.png b/packages/components/nodes/tools/Arxiv/arxiv.png new file mode 100644 index 0000000000000000000000000000000000000000..9311a6909aa3038d416173a90a92b2e2a46e1551 GIT binary patch literal 56182 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 literal 0 HcmV?d00001 diff --git a/packages/components/nodes/tools/Arxiv/core.ts b/packages/components/nodes/tools/Arxiv/core.ts new file mode 100644 index 00000000..a774eb3a --- /dev/null +++ b/packages/components/nodes/tools/Arxiv/core.ts @@ -0,0 +1,266 @@ +import { z } from 'zod' +import fetch from 'node-fetch' +import { PDFLoader } from '@langchain/community/document_loaders/fs/pdf' +import { DynamicStructuredTool } from '../OpenAPIToolkit/core' + +export const desc = `Use this tool to search for academic papers on Arxiv. You can search by keywords, topics, authors, or specific Arxiv IDs. The tool can return either paper summaries or download and extract full paper content.` + +export interface ArxivParameters { + topKResults?: number + maxQueryLength?: number + docContentCharsMax?: number + loadFullContent?: boolean + continueOnFailure?: boolean + legacyBuild?: boolean + name?: string + description?: string +} + +interface ArxivResult { + id: string + title: string + authors: string[] + summary: string + published: string + updated: string + entryId: string +} + +// Schema for Arxiv search +const createArxivSchema = () => { + return z.object({ + query: z + .string() + .describe('Search query for Arxiv papers. Can be keywords, topics, authors, or specific Arxiv IDs (e.g., 2301.12345)') + }) +} + +export class ArxivTool extends DynamicStructuredTool { + topKResults = 3 + maxQueryLength = 300 + docContentCharsMax = 4000 + loadFullContent = false + continueOnFailure = false + legacyBuild = false + logger?: any + orgId?: string + + constructor(args?: ArxivParameters, logger?: any, orgId?: string) { + const schema = createArxivSchema() + + const toolInput = { + name: args?.name || 'arxiv_search', + description: args?.description || desc, + schema: schema, + baseUrl: '', + method: 'GET', + headers: {} + } + super(toolInput) + this.topKResults = args?.topKResults ?? this.topKResults + this.maxQueryLength = args?.maxQueryLength ?? this.maxQueryLength + this.docContentCharsMax = args?.docContentCharsMax ?? this.docContentCharsMax + this.loadFullContent = args?.loadFullContent ?? this.loadFullContent + this.continueOnFailure = args?.continueOnFailure ?? this.continueOnFailure + this.legacyBuild = args?.legacyBuild ?? this.legacyBuild + this.logger = logger + this.orgId = orgId + } + + private isArxivIdentifier(query: string): boolean { + const arxivIdentifierPattern = /\d{2}(0[1-9]|1[0-2])\.\d{4,5}(v\d+|)|\d{7}.*/ + const queryItems = query.substring(0, this.maxQueryLength).split(/\s+/) + + for (const queryItem of queryItems) { + const match = queryItem.match(arxivIdentifierPattern) + if (!match || match[0] !== queryItem) { + return false + } + } + return true + } + + private parseArxivResponse(xmlText: string): ArxivResult[] { + const results: ArxivResult[] = [] + + // Simple XML parsing for Arxiv API response + const entryRegex = /(.*?)<\/entry>/gs + const entries = xmlText.match(entryRegex) || [] + + for (const entry of entries) { + try { + const id = this.extractXmlValue(entry, 'id') + const title = this.extractXmlValue(entry, 'title')?.replace(/\n\s+/g, ' ').trim() + const summary = this.extractXmlValue(entry, 'summary')?.replace(/\n\s+/g, ' ').trim() + const published = this.extractXmlValue(entry, 'published') + const updated = this.extractXmlValue(entry, 'updated') + + // Extract authors + const authorRegex = /(.*?)<\/name><\/author>/g + const authors: string[] = [] + let authorMatch + while ((authorMatch = authorRegex.exec(entry)) !== null) { + authors.push(authorMatch[1]) + } + + if (id && title && summary) { + results.push({ + id, + title, + authors, + summary, + published: published || '', + updated: updated || '', + entryId: id + }) + } + } catch (error) { + console.warn('Error parsing Arxiv entry:', error) + } + } + + return results + } + + private extractXmlValue(xml: string, tag: string): string | undefined { + const regex = new RegExp(`<${tag}[^>]*>(.*?)`, 's') + const match = xml.match(regex) + return match ? match[1] : undefined + } + + private async fetchResults(query: string): Promise { + const baseUrl = 'http://export.arxiv.org/api/query' + let searchParams: URLSearchParams + + if (this.isArxivIdentifier(query)) { + // Search by ID + const ids = query.split(/\s+/).join(',') + searchParams = new URLSearchParams({ + id_list: ids, + max_results: this.topKResults.toString() + }) + } else { + // Search by query + // Remove problematic characters that can cause search issues + const cleanedQuery = query.replace(/[:-]/g, '').substring(0, this.maxQueryLength) + searchParams = new URLSearchParams({ + search_query: `all:${cleanedQuery}`, + max_results: this.topKResults.toString(), + sortBy: 'relevance', + sortOrder: 'descending' + }) + } + + const url = `${baseUrl}?${searchParams.toString()}` + this.logger?.info(`[${this.orgId}]: Making Arxiv API call to: ${url}`) + + const response = await fetch(url) + if (!response.ok) { + throw new Error(`Arxiv API error: ${response.status} ${response.statusText}`) + } + + const xmlText = await response.text() + return this.parseArxivResponse(xmlText) + } + + private async downloadAndExtractPdf(arxivId: string): Promise { + // Extract clean arxiv ID from full URL if needed + const cleanId = arxivId.replace('http://arxiv.org/abs/', '').replace('https://arxiv.org/abs/', '') + const pdfUrl = `https://arxiv.org/pdf/${cleanId}.pdf` + + this.logger?.info(`[${this.orgId}]: Downloading PDF from: ${pdfUrl}`) + + const response = await fetch(pdfUrl) + if (!response.ok) { + throw new Error(`Failed to download PDF: ${response.status} ${response.statusText}`) + } + + // Get PDF buffer and create blob + const buffer = await response.buffer() + const blob = new Blob([buffer]) + + // Use PDFLoader to extract text (same as Pdf.ts) + const loader = new PDFLoader(blob, { + splitPages: false, + pdfjs: () => + // @ts-ignore + this.legacyBuild ? import('pdfjs-dist/legacy/build/pdf.js') : import('pdf-parse/lib/pdf.js/v1.10.100/build/pdf.js') + }) + + const docs = await loader.load() + return docs.map((doc) => doc.pageContent).join('\n') + } + + /** @ignore */ + async _call(arg: any): Promise { + const { query } = arg + + if (!query) { + throw new Error('Query is required for Arxiv search') + } + + try { + const results = await this.fetchResults(query) + + if (results.length === 0) { + return 'No good Arxiv Result was found' + } + + if (!this.loadFullContent) { + // Return summaries only (original behavior) + const docs = results.map((result) => { + const publishedDate = result.published ? new Date(result.published).toISOString().split('T')[0] : 'Unknown' + return `Published: ${publishedDate}\nTitle: ${result.title}\nAuthors: ${result.authors.join(', ')}\nSummary: ${ + result.summary + }` + }) + + const fullText = docs.join('\n\n') + return this.docContentCharsMax ? fullText.substring(0, this.docContentCharsMax) : fullText + } else { + // Download PDFs and extract full content + const docs: string[] = [] + + for (const result of results) { + try { + this.logger?.info(`[${this.orgId}]: Processing paper: ${result.title}`) + + // Download and extract PDF content + const fullText = await this.downloadAndExtractPdf(result.id) + + const publishedDate = result.published ? new Date(result.published).toISOString().split('T')[0] : 'Unknown' + + // Format with metadata and full content + const docContent = `Published: ${publishedDate}\nTitle: ${result.title}\nAuthors: ${result.authors.join( + ', ' + )}\nSummary: ${result.summary}\n\nFull Content:\n${fullText}` + + const truncatedContent = this.docContentCharsMax ? docContent.substring(0, this.docContentCharsMax) : docContent + + docs.push(truncatedContent) + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error' + console.error(`Error processing paper ${result.title}:`, errorMessage) + + if (!this.continueOnFailure) { + throw new Error(`Failed to process paper "${result.title}": ${errorMessage}`) + } else { + // Add error notice and continue with summary only + const publishedDate = result.published ? new Date(result.published).toISOString().split('T')[0] : 'Unknown' + const fallbackContent = `Published: ${publishedDate}\nTitle: ${result.title}\nAuthors: ${result.authors.join( + ', ' + )}\nSummary: ${result.summary}\n\n[ERROR: Could not load full content - ${errorMessage}]` + docs.push(fallbackContent) + } + } + } + + return docs.join('\n\n---\n\n') + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error' + console.error('Arxiv search error:', errorMessage) + throw new Error(`Failed to search Arxiv: ${errorMessage}`) + } + } +} diff --git a/packages/components/nodes/tools/ChatflowTool/ChatflowTool.ts b/packages/components/nodes/tools/ChatflowTool/ChatflowTool.ts index e473357f..993d12ae 100644 --- a/packages/components/nodes/tools/ChatflowTool/ChatflowTool.ts +++ b/packages/components/nodes/tools/ChatflowTool/ChatflowTool.ts @@ -23,7 +23,7 @@ class ChatflowTool_Tools implements INode { constructor() { this.label = 'Chatflow Tool' this.name = 'ChatflowTool' - this.version = 5.0 + this.version = 5.1 this.type = 'ChatflowTool' this.icon = 'chatflowTool.svg' this.category = 'Tools' @@ -106,7 +106,10 @@ class ChatflowTool_Tools implements INode { type: 'string', description: 'Custom input to be passed to the chatflow. Leave empty to let LLM decides the input.', optional: true, - additionalParams: true + additionalParams: true, + show: { + useQuestionFromChat: false + } } ] } @@ -126,9 +129,20 @@ class ChatflowTool_Tools implements INode { const chatflows = await appDataSource.getRepository(databaseEntities['ChatFlow']).findBy(searchOptions) for (let i = 0; i < chatflows.length; i += 1) { + let type = chatflows[i].type + if (type === 'AGENTFLOW') { + type = 'AgentflowV2' + } else if (type === 'MULTIAGENT') { + type = 'AgentflowV1' + } else if (type === 'ASSISTANT') { + type = 'Custom Assistant' + } else { + type = 'Chatflow' + } const data = { label: chatflows[i].name, - name: chatflows[i].id + name: chatflows[i].id, + description: type } as INodeOptionsValue returnData.push(data) } diff --git a/packages/components/nodes/tools/OpenAPIToolkit/OpenAPIToolkit.ts b/packages/components/nodes/tools/OpenAPIToolkit/OpenAPIToolkit.ts index 23ef589a..ccc7ef7d 100644 --- a/packages/components/nodes/tools/OpenAPIToolkit/OpenAPIToolkit.ts +++ b/packages/components/nodes/tools/OpenAPIToolkit/OpenAPIToolkit.ts @@ -243,6 +243,9 @@ const getTools = ( const methods = paths[path] for (const method in methods) { // example of method: "get" + if (method !== 'get' && method !== 'post' && method !== 'put' && method !== 'delete' && method !== 'patch') { + continue + } const spec = methods[method] const toolName = spec.operationId const toolDesc = spec.description || spec.summary || toolName @@ -318,7 +321,7 @@ const getTools = ( dynamicStructuredTool.setVariables(variables) dynamicStructuredTool.setFlowObject(flow) dynamicStructuredTool.returnDirect = returnDirect - tools.push(dynamicStructuredTool) + if (toolName && toolDesc) tools.push(dynamicStructuredTool) } } return tools diff --git a/packages/components/nodes/tools/RequestsDelete/RequestsDelete.ts b/packages/components/nodes/tools/RequestsDelete/RequestsDelete.ts new file mode 100644 index 00000000..5cdf47c4 --- /dev/null +++ b/packages/components/nodes/tools/RequestsDelete/RequestsDelete.ts @@ -0,0 +1,141 @@ +import { INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses, stripHTMLFromToolInput } from '../../../src/utils' +import { desc, RequestParameters, RequestsDeleteTool } from './core' + +const codeExample = `{ + "id": { + "type": "string", + "required": true, + "in": "path", + "description": "ID of the item to delete. /:id" + }, + "force": { + "type": "string", + "in": "query", + "description": "Force delete the item. ?force=true" + } +}` + +class RequestsDelete_Tools implements INode { + label: string + name: string + version: number + description: string + type: string + icon: string + category: string + baseClasses: string[] + inputs: INodeParams[] + + constructor() { + this.label = 'Requests Delete' + this.name = 'requestsDelete' + this.version = 1.0 + this.type = 'RequestsDelete' + this.icon = 'del.png' + this.category = 'Tools' + this.description = 'Execute HTTP DELETE requests' + this.baseClasses = [this.type, ...getBaseClasses(RequestsDeleteTool)] + this.inputs = [ + { + label: 'URL', + name: 'requestsDeleteUrl', + type: 'string', + acceptVariable: true + }, + { + label: 'Name', + name: 'requestsDeleteName', + type: 'string', + default: 'requests_delete', + description: 'Name of the tool', + additionalParams: true, + optional: true + }, + { + label: 'Description', + name: 'requestsDeleteDescription', + type: 'string', + rows: 4, + default: desc, + description: 'Describe to LLM when it should use this tool', + additionalParams: true, + optional: true + }, + { + label: 'Headers', + name: 'requestsDeleteHeaders', + type: 'string', + rows: 4, + acceptVariable: true, + additionalParams: true, + optional: true, + placeholder: `{ + "Authorization": "Bearer " +}` + }, + { + label: 'Query Params Schema', + name: 'requestsDeleteQueryParamsSchema', + type: 'code', + description: 'Description of the available query params to enable LLM to figure out which query params to use', + placeholder: `{ + "id": { + "type": "string", + "required": true, + "in": "path", + "description": "ID of the item to delete. /:id" + }, + "force": { + "type": "string", + "in": "query", + "description": "Force delete the item. ?force=true" + } +}`, + optional: true, + hideCodeExecute: true, + additionalParams: true, + codeExample: codeExample + }, + { + label: 'Max Output Length', + name: 'requestsDeleteMaxOutputLength', + type: 'number', + description: 'Max length of the output. Remove this if you want to return the entire response', + default: '2000', + step: 1, + optional: true, + additionalParams: true + } + ] + } + + async init(nodeData: INodeData): Promise { + const headers = (nodeData.inputs?.headers as string) || (nodeData.inputs?.requestsDeleteHeaders as string) + const url = (nodeData.inputs?.url as string) || (nodeData.inputs?.requestsDeleteUrl as string) + const description = (nodeData.inputs?.description as string) || (nodeData.inputs?.requestsDeleteDescription as string) + const name = (nodeData.inputs?.name as string) || (nodeData.inputs?.requestsDeleteName as string) + const queryParamsSchema = + (nodeData.inputs?.queryParamsSchema as string) || (nodeData.inputs?.requestsDeleteQueryParamsSchema as string) + const maxOutputLength = nodeData.inputs?.requestsDeleteMaxOutputLength as string + + const obj: RequestParameters = {} + if (url) obj.url = stripHTMLFromToolInput(url) + if (description) obj.description = description + if (name) + obj.name = name + .toLowerCase() + .replace(/ /g, '_') + .replace(/[^a-z0-9_-]/g, '') + if (queryParamsSchema) obj.queryParamsSchema = queryParamsSchema + if (maxOutputLength) obj.maxOutputLength = parseInt(maxOutputLength, 10) + if (headers) { + const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(stripHTMLFromToolInput(headers)) + obj.headers = parsedHeaders + } + + return new RequestsDeleteTool(obj) + } +} + +module.exports = { nodeClass: RequestsDelete_Tools } diff --git a/packages/components/nodes/tools/RequestsDelete/core.ts b/packages/components/nodes/tools/RequestsDelete/core.ts new file mode 100644 index 00000000..d753ca08 --- /dev/null +++ b/packages/components/nodes/tools/RequestsDelete/core.ts @@ -0,0 +1,184 @@ +import { z } from 'zod' +import fetch from 'node-fetch' +import { DynamicStructuredTool } from '../OpenAPIToolkit/core' + +export const desc = `Use this when you need to execute a DELETE request to remove data from a website.` + +export interface Headers { + [key: string]: string +} + +export interface RequestParameters { + headers?: Headers + url?: string + name?: string + queryParamsSchema?: string + description?: string + maxOutputLength?: number +} + +// Base schema for DELETE request +const createRequestsDeleteSchema = (queryParamsSchema?: string) => { + // If queryParamsSchema is provided, parse it and add dynamic query params + if (queryParamsSchema) { + try { + const parsedSchema = JSON.parse(queryParamsSchema) + const queryParamsObject: Record = {} + + Object.entries(parsedSchema).forEach(([key, config]: [string, any]) => { + let zodType: z.ZodTypeAny = z.string() + + // Handle different types + if (config.type === 'number') { + zodType = z.string().transform((val) => Number(val)) + } else if (config.type === 'boolean') { + zodType = z.string().transform((val) => val === 'true') + } + + // Add description + if (config.description) { + zodType = zodType.describe(config.description) + } + + // Make optional if not required + if (!config.required) { + zodType = zodType.optional() + } + + queryParamsObject[key] = zodType + }) + + if (Object.keys(queryParamsObject).length > 0) { + return z.object({ + queryParams: z.object(queryParamsObject).optional().describe('Query parameters for the request') + }) + } + } catch (error) { + console.warn('Failed to parse queryParamsSchema:', error) + } + } + + // Fallback to generic query params + return z.object({ + queryParams: z.record(z.string()).optional().describe('Optional query parameters to include in the request') + }) +} + +export class RequestsDeleteTool extends DynamicStructuredTool { + url = '' + maxOutputLength = Infinity + headers = {} + queryParamsSchema?: string + + constructor(args?: RequestParameters) { + const schema = createRequestsDeleteSchema(args?.queryParamsSchema) + + const toolInput = { + name: args?.name || 'requests_delete', + description: args?.description || desc, + schema: schema, + baseUrl: '', + method: 'DELETE', + headers: args?.headers || {} + } + super(toolInput) + this.url = args?.url ?? this.url + this.headers = args?.headers ?? this.headers + this.maxOutputLength = args?.maxOutputLength ?? this.maxOutputLength + this.queryParamsSchema = args?.queryParamsSchema + } + + /** @ignore */ + async _call(arg: any): Promise { + const params = { ...arg } + + const inputUrl = this.url + if (!inputUrl) { + throw new Error('URL is required for DELETE request') + } + + const requestHeaders = { + ...(params.headers || {}), + ...this.headers + } + + // Process URL and query parameters based on schema + let finalUrl = inputUrl + const queryParams: Record = {} + + if (this.queryParamsSchema && params.queryParams && Object.keys(params.queryParams).length > 0) { + try { + const parsedSchema = JSON.parse(this.queryParamsSchema) + const pathParams: Array<{ key: string; value: string }> = [] + + Object.entries(params.queryParams).forEach(([key, value]) => { + const paramConfig = parsedSchema[key] + if (paramConfig && value !== undefined && value !== null) { + if (paramConfig.in === 'path') { + // Check if URL contains path parameter placeholder + const pathPattern = new RegExp(`:${key}\\b`, 'g') + if (finalUrl.includes(`:${key}`)) { + // Replace path parameters in URL (e.g., /:id -> /123) + finalUrl = finalUrl.replace(pathPattern, encodeURIComponent(String(value))) + } else { + // Collect path parameters to append to URL + pathParams.push({ key, value: String(value) }) + } + } else if (paramConfig.in === 'query') { + // Add to query parameters + queryParams[key] = String(value) + } + } + }) + + // Append path parameters to URL if any exist + if (pathParams.length > 0) { + let urlPath = finalUrl + // Remove trailing slash if present + if (urlPath.endsWith('/')) { + urlPath = urlPath.slice(0, -1) + } + // Append each path parameter + pathParams.forEach(({ value }) => { + urlPath += `/${encodeURIComponent(value)}` + }) + finalUrl = urlPath + } + + // Add query parameters to URL if any exist + if (Object.keys(queryParams).length > 0) { + const url = new URL(finalUrl) + Object.entries(queryParams).forEach(([key, value]) => { + url.searchParams.append(key, value) + }) + finalUrl = url.toString() + } + } catch (error) { + console.warn('Failed to process queryParamsSchema:', error) + } + } else if (params.queryParams && Object.keys(params.queryParams).length > 0) { + // Fallback: treat all parameters as query parameters if no schema is defined + const url = new URL(finalUrl) + Object.entries(params.queryParams).forEach(([key, value]) => { + url.searchParams.append(key, String(value)) + }) + finalUrl = url.toString() + } + + try { + const res = await fetch(finalUrl, { + method: 'DELETE', + headers: requestHeaders + }) + + if (!res.ok) { + throw new Error(`HTTP Error ${res.status}: ${res.statusText}`) + } + + const text = await res.text() + return text.slice(0, this.maxOutputLength) + } catch (error) { + throw new Error(`Failed to make DELETE request: ${error instanceof Error ? error.message : 'Unknown error'}`) + } + } +} diff --git a/packages/components/nodes/tools/RequestsDelete/del.png b/packages/components/nodes/tools/RequestsDelete/del.png new file mode 100644 index 0000000000000000000000000000000000000000..dead64c466db178d8211fb34bfbae16221fe8488 GIT binary patch literal 10176 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 literal 0 HcmV?d00001 diff --git a/packages/components/nodes/tools/RequestsGet/RequestsGet.ts b/packages/components/nodes/tools/RequestsGet/RequestsGet.ts index 91cff500..84efe0b8 100644 --- a/packages/components/nodes/tools/RequestsGet/RequestsGet.ts +++ b/packages/components/nodes/tools/RequestsGet/RequestsGet.ts @@ -1,7 +1,21 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' -import { getBaseClasses } from '../../../src/utils' +import { getBaseClasses, stripHTMLFromToolInput } from '../../../src/utils' import { desc, RequestParameters, RequestsGetTool } from './core' +const codeExample = `{ + "id": { + "type": "string", + "required": true, + "in": "path", + "description": "ID of the item to get. /:id" + }, + "limit": { + "type": "string", + "in": "query", + "description": "Limit the number of items to get. ?limit=10" + } +}` + class RequestsGet_Tools implements INode { label: string name: string @@ -16,52 +30,107 @@ class RequestsGet_Tools implements INode { constructor() { this.label = 'Requests Get' this.name = 'requestsGet' - this.version = 1.0 + this.version = 2.0 this.type = 'RequestsGet' - this.icon = 'requestsget.svg' + this.icon = 'get.png' this.category = 'Tools' this.description = 'Execute HTTP GET requests' this.baseClasses = [this.type, ...getBaseClasses(RequestsGetTool)] this.inputs = [ { label: 'URL', - name: 'url', + name: 'requestsGetUrl', type: 'string', - description: - 'Agent will make call to this exact URL. If not specified, agent will try to figure out itself from AIPlugin if provided', + acceptVariable: true + }, + { + label: 'Name', + name: 'requestsGetName', + type: 'string', + default: 'requests_get', + description: 'Name of the tool', additionalParams: true, optional: true }, { label: 'Description', - name: 'description', + name: 'requestsGetDescription', type: 'string', rows: 4, default: desc, - description: 'Acts like a prompt to tell agent when it should use this tool', + description: 'Describe to LLM when it should use this tool', additionalParams: true, optional: true }, { label: 'Headers', - name: 'headers', - type: 'json', + name: 'requestsGetHeaders', + type: 'string', + rows: 4, + acceptVariable: true, additionalParams: true, - optional: true + optional: true, + placeholder: `{ + "Authorization": "Bearer " +}` + }, + { + label: 'Query Params Schema', + name: 'requestsGetQueryParamsSchema', + type: 'code', + description: 'Description of the available query params to enable LLM to figure out which query params to use', + placeholder: `{ + "id": { + "type": "string", + "required": true, + "in": "path", + "description": "ID of the item to get. /:id" + }, + "limit": { + "type": "string", + "in": "query", + "description": "Limit the number of items to get. ?limit=10" + } +}`, + optional: true, + hideCodeExecute: true, + additionalParams: true, + codeExample: codeExample + }, + { + label: 'Max Output Length', + name: 'requestsGetMaxOutputLength', + type: 'number', + description: 'Max length of the output. Remove this if you want to return the entire response', + default: '2000', + step: 1, + optional: true, + additionalParams: true } ] } async init(nodeData: INodeData): Promise { - const headers = nodeData.inputs?.headers as string - const url = nodeData.inputs?.url as string - const description = nodeData.inputs?.description as string + const headers = (nodeData.inputs?.headers as string) || (nodeData.inputs?.requestsGetHeaders as string) + const url = (nodeData.inputs?.url as string) || (nodeData.inputs?.requestsGetUrl as string) + const description = (nodeData.inputs?.description as string) || (nodeData.inputs?.requestsGetDescription as string) + const name = (nodeData.inputs?.name as string) || (nodeData.inputs?.requestsGetName as string) + const queryParamsSchema = + (nodeData.inputs?.queryParamsSchema as string) || (nodeData.inputs?.requestsGetQueryParamsSchema as string) + const maxOutputLength = nodeData.inputs?.requestsGetMaxOutputLength as string const obj: RequestParameters = {} - if (url) obj.url = url + if (url) obj.url = stripHTMLFromToolInput(url) if (description) obj.description = description + if (name) + obj.name = name + .toLowerCase() + .replace(/ /g, '_') + .replace(/[^a-z0-9_-]/g, '') + if (queryParamsSchema) obj.queryParamsSchema = queryParamsSchema + if (maxOutputLength) obj.maxOutputLength = parseInt(maxOutputLength, 10) if (headers) { - const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(headers) + const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(stripHTMLFromToolInput(headers)) obj.headers = parsedHeaders } diff --git a/packages/components/nodes/tools/RequestsGet/core.ts b/packages/components/nodes/tools/RequestsGet/core.ts index ea97cdf2..603da4ff 100644 --- a/packages/components/nodes/tools/RequestsGet/core.ts +++ b/packages/components/nodes/tools/RequestsGet/core.ts @@ -1,8 +1,8 @@ +import { z } from 'zod' import fetch from 'node-fetch' -import { Tool } from '@langchain/core/tools' +import { DynamicStructuredTool } from '../OpenAPIToolkit/core' -export const desc = `A portal to the internet. Use this when you need to get specific content from a website. -Input should be a url (i.e. https://www.google.com). The output will be the text response of the GET request.` +export const desc = `Use this when you need to execute a GET request to get data from a website.` export interface Headers { [key: string]: string @@ -11,36 +11,173 @@ export interface Headers { export interface RequestParameters { headers?: Headers url?: string + name?: string + queryParamsSchema?: string description?: string maxOutputLength?: number } -export class RequestsGetTool extends Tool { - name = 'requests_get' +// Base schema for GET request +const createRequestsGetSchema = (queryParamsSchema?: string) => { + // If queryParamsSchema is provided, parse it and add dynamic query params + if (queryParamsSchema) { + try { + const parsedSchema = JSON.parse(queryParamsSchema) + const queryParamsObject: Record = {} + + Object.entries(parsedSchema).forEach(([key, config]: [string, any]) => { + let zodType: z.ZodTypeAny = z.string() + + // Handle different types + if (config.type === 'number') { + zodType = z.string().transform((val) => Number(val)) + } else if (config.type === 'boolean') { + zodType = z.string().transform((val) => val === 'true') + } + + // Add description + if (config.description) { + zodType = zodType.describe(config.description) + } + + // Make optional if not required + if (!config.required) { + zodType = zodType.optional() + } + + queryParamsObject[key] = zodType + }) + + if (Object.keys(queryParamsObject).length > 0) { + return z.object({ + queryParams: z.object(queryParamsObject).optional().describe('Query parameters for the request') + }) + } + } catch (error) { + console.warn('Failed to parse queryParamsSchema:', error) + } + } + + // Fallback to generic query params + return z.object({ + queryParams: z.record(z.string()).optional().describe('Optional query parameters to include in the request') + }) +} + +export class RequestsGetTool extends DynamicStructuredTool { url = '' - description = desc - maxOutputLength = 2000 + maxOutputLength = Infinity headers = {} + queryParamsSchema?: string constructor(args?: RequestParameters) { - super() + const schema = createRequestsGetSchema(args?.queryParamsSchema) + + const toolInput = { + name: args?.name || 'requests_get', + description: args?.description || desc, + schema: schema, + baseUrl: '', + method: 'GET', + headers: args?.headers || {} + } + super(toolInput) this.url = args?.url ?? this.url this.headers = args?.headers ?? this.headers - this.description = args?.description ?? this.description this.maxOutputLength = args?.maxOutputLength ?? this.maxOutputLength + this.queryParamsSchema = args?.queryParamsSchema } /** @ignore */ - async _call(input: string) { - const inputUrl = !this.url ? input : this.url + async _call(arg: any): Promise { + const params = { ...arg } - if (process.env.DEBUG === 'true') console.info(`Making GET API call to ${inputUrl}`) + const inputUrl = this.url + if (!inputUrl) { + throw new Error('URL is required for GET request') + } - const res = await fetch(inputUrl, { - headers: this.headers - }) + const requestHeaders = { + ...(params.headers || {}), + ...this.headers + } - const text = await res.text() - return text.slice(0, this.maxOutputLength) + // Process URL and query parameters based on schema + let finalUrl = inputUrl + const queryParams: Record = {} + + if (this.queryParamsSchema && params.queryParams && Object.keys(params.queryParams).length > 0) { + try { + const parsedSchema = JSON.parse(this.queryParamsSchema) + const pathParams: Array<{ key: string; value: string }> = [] + + Object.entries(params.queryParams).forEach(([key, value]) => { + const paramConfig = parsedSchema[key] + if (paramConfig && value !== undefined && value !== null) { + if (paramConfig.in === 'path') { + // Check if URL contains path parameter placeholder + const pathPattern = new RegExp(`:${key}\\b`, 'g') + if (finalUrl.includes(`:${key}`)) { + // Replace path parameters in URL (e.g., /:id -> /123) + finalUrl = finalUrl.replace(pathPattern, encodeURIComponent(String(value))) + } else { + // Collect path parameters to append to URL + pathParams.push({ key, value: String(value) }) + } + } else if (paramConfig.in === 'query') { + // Add to query parameters + queryParams[key] = String(value) + } + } + }) + + // Append path parameters to URL if any exist + if (pathParams.length > 0) { + let urlPath = finalUrl + // Remove trailing slash if present + if (urlPath.endsWith('/')) { + urlPath = urlPath.slice(0, -1) + } + // Append each path parameter + pathParams.forEach(({ value }) => { + urlPath += `/${encodeURIComponent(value)}` + }) + finalUrl = urlPath + } + + // Add query parameters to URL if any exist + if (Object.keys(queryParams).length > 0) { + const url = new URL(finalUrl) + Object.entries(queryParams).forEach(([key, value]) => { + url.searchParams.append(key, value) + }) + finalUrl = url.toString() + } + } catch (error) { + console.warn('Failed to process queryParamsSchema:', error) + } + } else if (params.queryParams && Object.keys(params.queryParams).length > 0) { + // Fallback: treat all parameters as query parameters if no schema is defined + const url = new URL(finalUrl) + Object.entries(params.queryParams).forEach(([key, value]) => { + url.searchParams.append(key, String(value)) + }) + finalUrl = url.toString() + } + + try { + const res = await fetch(finalUrl, { + headers: requestHeaders + }) + + if (!res.ok) { + throw new Error(`HTTP Error ${res.status}: ${res.statusText}`) + } + + const text = await res.text() + return text.slice(0, this.maxOutputLength) + } catch (error) { + throw new Error(`Failed to make GET request: ${error instanceof Error ? error.message : 'Unknown error'}`) + } } } diff --git a/packages/components/nodes/tools/RequestsGet/get.png b/packages/components/nodes/tools/RequestsGet/get.png new file mode 100644 index 0000000000000000000000000000000000000000..ac859c47f3e4424438ec8198c7b3219f7dcd4c60 GIT binary patch literal 7665 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 QwQ>RK7;W@d6 - - - - - diff --git a/packages/components/nodes/tools/RequestsPost/RequestsPost.ts b/packages/components/nodes/tools/RequestsPost/RequestsPost.ts index 9ff3d142..e229711a 100644 --- a/packages/components/nodes/tools/RequestsPost/RequestsPost.ts +++ b/packages/components/nodes/tools/RequestsPost/RequestsPost.ts @@ -1,7 +1,19 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' -import { getBaseClasses } from '../../../src/utils' +import { getBaseClasses, stripHTMLFromToolInput } from '../../../src/utils' import { RequestParameters, desc, RequestsPostTool } from './core' +const codeExample = `{ + "name": { + "type": "string", + "required": true, + "description": "Name of the item" + }, + "date": { + "type": "string", + "description": "Date of the item" + } +}` + class RequestsPost_Tools implements INode { label: string name: string @@ -16,62 +28,119 @@ class RequestsPost_Tools implements INode { constructor() { this.label = 'Requests Post' this.name = 'requestsPost' - this.version = 1.0 + this.version = 2.0 this.type = 'RequestsPost' - this.icon = 'requestspost.svg' + this.icon = 'post.png' this.category = 'Tools' this.description = 'Execute HTTP POST requests' this.baseClasses = [this.type, ...getBaseClasses(RequestsPostTool)] this.inputs = [ { label: 'URL', - name: 'url', + name: 'requestsPostUrl', type: 'string', - description: - 'Agent will make call to this exact URL. If not specified, agent will try to figure out itself from AIPlugin if provided', - additionalParams: true, - optional: true + acceptVariable: true }, { - label: 'Body', - name: 'body', - type: 'json', - description: - 'JSON body for the POST request. If not specified, agent will try to figure out itself from AIPlugin if provided', + label: 'Name', + name: 'requestsPostName', + type: 'string', + default: 'requests_post', + description: 'Name of the tool', additionalParams: true, optional: true }, { label: 'Description', - name: 'description', + name: 'requestsPostDescription', type: 'string', rows: 4, default: desc, - description: 'Acts like a prompt to tell agent when it should use this tool', + description: 'Describe to LLM when it should use this tool', additionalParams: true, optional: true }, { label: 'Headers', - name: 'headers', - type: 'json', + name: 'requestsPostHeaders', + type: 'string', + rows: 4, + acceptVariable: true, additionalParams: true, - optional: true + optional: true, + placeholder: `{ + "Authorization": "Bearer " +}` + }, + { + label: 'Body', + name: 'requestPostBody', + type: 'string', + rows: 4, + description: 'JSON body for the POST request. This will override the body generated by the LLM', + additionalParams: true, + acceptVariable: true, + optional: true, + placeholder: `{ + "name": "John Doe", + "age": 30 +}` + }, + { + label: 'Body Schema', + name: 'requestsPostBodySchema', + type: 'code', + description: 'Description of the available body params to enable LLM to figure out which body params to use', + placeholder: `{ + "name": { + "type": "string", + "required": true, + "description": "Name of the item" + }, + "date": { + "type": "string", + "description": "Date of the item" + } +}`, + optional: true, + hideCodeExecute: true, + additionalParams: true, + codeExample: codeExample + }, + { + label: 'Max Output Length', + name: 'requestsPostMaxOutputLength', + type: 'number', + description: 'Max length of the output. Remove this if you want to return the entire response', + default: '2000', + step: 1, + optional: true, + additionalParams: true } ] } async init(nodeData: INodeData): Promise { - const headers = nodeData.inputs?.headers as string - const url = nodeData.inputs?.url as string - const description = nodeData.inputs?.description as string - const body = nodeData.inputs?.body as string + const headers = (nodeData.inputs?.headers as string) || (nodeData.inputs?.requestsPostHeaders as string) + const url = (nodeData.inputs?.url as string) || (nodeData.inputs?.requestsPostUrl as string) + const name = (nodeData.inputs?.name as string) || (nodeData.inputs?.requestsPostName as string) + const description = (nodeData.inputs?.description as string) || (nodeData.inputs?.requestsPostDescription as string) + const body = (nodeData.inputs?.body as string) || (nodeData.inputs?.requestPostBody as string) + const bodySchema = nodeData.inputs?.requestsPostBodySchema as string + const maxOutputLength = (nodeData.inputs?.maxOutputLength as string) || (nodeData.inputs?.requestsPostMaxOutputLength as string) const obj: RequestParameters = {} - if (url) obj.url = url + if (url) obj.url = stripHTMLFromToolInput(url) if (description) obj.description = description + if (name) + obj.name = name + .toLowerCase() + .replace(/ /g, '_') + .replace(/[^a-z0-9_-]/g, '') + if (bodySchema) obj.bodySchema = stripHTMLFromToolInput(bodySchema) + if (maxOutputLength) obj.maxOutputLength = parseInt(maxOutputLength, 10) if (headers) { - const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(headers) + const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(stripHTMLFromToolInput(headers)) obj.headers = parsedHeaders } if (body) { diff --git a/packages/components/nodes/tools/RequestsPost/core.ts b/packages/components/nodes/tools/RequestsPost/core.ts index a380f167..3360dcc2 100644 --- a/packages/components/nodes/tools/RequestsPost/core.ts +++ b/packages/components/nodes/tools/RequestsPost/core.ts @@ -1,12 +1,8 @@ -import { Tool } from '@langchain/core/tools' +import { z } from 'zod' import fetch from 'node-fetch' +import { DynamicStructuredTool } from '../OpenAPIToolkit/core' -export const desc = `Use this when you want to POST to a website. -Input should be a json string with two keys: "url" and "data". -The value of "url" should be a string, and the value of "data" should be a dictionary of -key-value pairs you want to POST to the url as a JSON body. -Be careful to always use double quotes for strings in the json string -The output will be the text response of the POST request.` +export const desc = `Use this when you want to execute a POST request to create or update a resource.` export interface Headers { [key: string]: string @@ -21,52 +17,129 @@ export interface RequestParameters { body?: Body url?: string description?: string + name?: string + bodySchema?: string maxOutputLength?: number } -export class RequestsPostTool extends Tool { - name = 'requests_post' +// Base schema for POST request +const createRequestsPostSchema = (bodySchema?: string) => { + // If bodySchema is provided, parse it and add dynamic body params + if (bodySchema) { + try { + const parsedSchema = JSON.parse(bodySchema) + const bodyParamsObject: Record = {} + + Object.entries(parsedSchema).forEach(([key, config]: [string, any]) => { + let zodType: z.ZodTypeAny = z.string() + + // Handle different types + if (config.type === 'number') { + zodType = z.number() + } else if (config.type === 'boolean') { + zodType = z.boolean() + } else if (config.type === 'object') { + zodType = z.record(z.any()) + } else if (config.type === 'array') { + zodType = z.array(z.any()) + } + + // Add description + if (config.description) { + zodType = zodType.describe(config.description) + } + + // Make optional if not required + if (!config.required) { + zodType = zodType.optional() + } + + bodyParamsObject[key] = zodType + }) + + if (Object.keys(bodyParamsObject).length > 0) { + return z.object({ + body: z.object(bodyParamsObject).describe('Request body parameters') + }) + } + } catch (error) { + console.warn('Failed to parse bodySchema:', error) + } + } + + // Fallback to generic body + return z.object({ + body: z.record(z.any()).optional().describe('Optional body data to include in the request') + }) +} + +export class RequestsPostTool extends DynamicStructuredTool { url = '' - description = desc maxOutputLength = Infinity headers = {} body = {} + bodySchema?: string constructor(args?: RequestParameters) { - super() + const schema = createRequestsPostSchema(args?.bodySchema) + + const toolInput = { + name: args?.name || 'requests_post', + description: args?.description || desc, + schema: schema, + baseUrl: '', + method: 'POST', + headers: args?.headers || {} + } + super(toolInput) this.url = args?.url ?? this.url this.headers = args?.headers ?? this.headers this.body = args?.body ?? this.body - this.description = args?.description ?? this.description this.maxOutputLength = args?.maxOutputLength ?? this.maxOutputLength + this.bodySchema = args?.bodySchema } /** @ignore */ - async _call(input: string) { + async _call(arg: any): Promise { + const params = { ...arg } + try { - let inputUrl = '' - let inputBody = {} - if (Object.keys(this.body).length || this.url) { - if (this.url) inputUrl = this.url - if (Object.keys(this.body).length) inputBody = this.body - } else { - const { url, data } = JSON.parse(input) - inputUrl = url - inputBody = data + const inputUrl = this.url + if (!inputUrl) { + throw new Error('URL is required for POST request') } - if (process.env.DEBUG === 'true') console.info(`Making POST API call to ${inputUrl} with body ${JSON.stringify(inputBody)}`) + let inputBody = { + ...this.body + } + + if (this.bodySchema && params.body && Object.keys(params.body).length > 0) { + inputBody = { + ...inputBody, + ...params.body + } + } + + const requestHeaders = { + 'Content-Type': 'application/json', + ...(params.headers || {}), + ...this.headers + } const res = await fetch(inputUrl, { method: 'POST', - headers: this.headers, + headers: requestHeaders, body: JSON.stringify(inputBody) }) + if (!res.ok) { + throw new Error(`HTTP Error ${res.status}: ${res.statusText}`) + } + const text = await res.text() return text.slice(0, this.maxOutputLength) } catch (error) { - return `${error}` + throw new Error(`Failed to make POST request: ${error instanceof Error ? error.message : 'Unknown error'}`) } } } diff --git a/packages/components/nodes/tools/RequestsPost/post.png b/packages/components/nodes/tools/RequestsPost/post.png new file mode 100644 index 0000000000000000000000000000000000000000..da409d5be8a81fec357eff3312d0d43089fc502c GIT binary patch literal 11341 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 CKdIUP literal 0 HcmV?d00001 diff --git a/packages/components/nodes/tools/RequestsPost/requestspost.svg b/packages/components/nodes/tools/RequestsPost/requestspost.svg deleted file mode 100644 index 477b1baf..00000000 --- a/packages/components/nodes/tools/RequestsPost/requestspost.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/packages/components/nodes/tools/RequestsPut/RequestsPut.ts b/packages/components/nodes/tools/RequestsPut/RequestsPut.ts new file mode 100644 index 00000000..a50d84fa --- /dev/null +++ b/packages/components/nodes/tools/RequestsPut/RequestsPut.ts @@ -0,0 +1,155 @@ +import { INode, INodeData, INodeParams } from '../../../src/Interface' +import { getBaseClasses, stripHTMLFromToolInput } from '../../../src/utils' +import { RequestParameters, desc, RequestsPutTool } from './core' + +const codeExample = `{ + "name": { + "type": "string", + "required": true, + "description": "Name of the item" + }, + "date": { + "type": "string", + "description": "Date of the item" + } +}` + +class RequestsPut_Tools implements INode { + label: string + name: string + version: number + description: string + type: string + icon: string + category: string + baseClasses: string[] + inputs: INodeParams[] + + constructor() { + this.label = 'Requests Put' + this.name = 'requestsPut' + this.version = 1.0 + this.type = 'RequestsPut' + this.icon = 'put.png' + this.category = 'Tools' + this.description = 'Execute HTTP PUT requests' + this.baseClasses = [this.type, ...getBaseClasses(RequestsPutTool)] + this.inputs = [ + { + label: 'URL', + name: 'requestsPutUrl', + type: 'string', + acceptVariable: true + }, + { + label: 'Name', + name: 'requestsPutName', + type: 'string', + default: 'requests_put', + description: 'Name of the tool', + additionalParams: true, + optional: true + }, + { + label: 'Description', + name: 'requestsPutDescription', + type: 'string', + rows: 4, + default: desc, + description: 'Describe to LLM when it should use this tool', + additionalParams: true, + optional: true + }, + { + label: 'Headers', + name: 'requestsPutHeaders', + type: 'string', + rows: 4, + acceptVariable: true, + additionalParams: true, + optional: true, + placeholder: `{ + "Authorization": "Bearer " +}` + }, + { + label: 'Body', + name: 'requestPutBody', + type: 'string', + rows: 4, + description: 'JSON body for the PUT request. This will override the body generated by the LLM', + additionalParams: true, + acceptVariable: true, + optional: true, + placeholder: `{ + "name": "John Doe", + "age": 30 +}` + }, + { + label: 'Body Schema', + name: 'requestsPutBodySchema', + type: 'code', + description: 'Description of the available body params to enable LLM to figure out which body params to use', + placeholder: `{ + "name": { + "type": "string", + "required": true, + "description": "Name of the item" + }, + "date": { + "type": "string", + "description": "Date of the item" + } +}`, + optional: true, + hideCodeExecute: true, + additionalParams: true, + codeExample: codeExample + }, + { + label: 'Max Output Length', + name: 'requestsPutMaxOutputLength', + type: 'number', + description: 'Max length of the output. Remove this if you want to return the entire response', + default: '2000', + step: 1, + optional: true, + additionalParams: true + } + ] + } + + async init(nodeData: INodeData): Promise { + const headers = (nodeData.inputs?.headers as string) || (nodeData.inputs?.requestsPutHeaders as string) + const url = (nodeData.inputs?.url as string) || (nodeData.inputs?.requestsPutUrl as string) + const name = (nodeData.inputs?.name as string) || (nodeData.inputs?.requestsPutName as string) + const description = (nodeData.inputs?.description as string) || (nodeData.inputs?.requestsPutDescription as string) + const body = (nodeData.inputs?.body as string) || (nodeData.inputs?.requestPutBody as string) + const bodySchema = nodeData.inputs?.requestsPutBodySchema as string + const maxOutputLength = (nodeData.inputs?.maxOutputLength as string) || (nodeData.inputs?.requestsPutMaxOutputLength as string) + + const obj: RequestParameters = {} + if (url) obj.url = stripHTMLFromToolInput(url) + if (description) obj.description = description + if (name) + obj.name = name + .toLowerCase() + .replace(/ /g, '_') + .replace(/[^a-z0-9_-]/g, '') + if (bodySchema) obj.bodySchema = stripHTMLFromToolInput(bodySchema) + if (maxOutputLength) obj.maxOutputLength = parseInt(maxOutputLength, 10) + if (headers) { + const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(stripHTMLFromToolInput(headers)) + obj.headers = parsedHeaders + } + if (body) { + const parsedBody = typeof body === 'object' ? body : JSON.parse(body) + obj.body = parsedBody + } + + return new RequestsPutTool(obj) + } +} + +module.exports = { nodeClass: RequestsPut_Tools } diff --git a/packages/components/nodes/tools/RequestsPut/core.ts b/packages/components/nodes/tools/RequestsPut/core.ts new file mode 100644 index 00000000..da937058 --- /dev/null +++ b/packages/components/nodes/tools/RequestsPut/core.ts @@ -0,0 +1,145 @@ +import { z } from 'zod' +import fetch from 'node-fetch' +import { DynamicStructuredTool } from '../OpenAPIToolkit/core' + +export const desc = `Use this when you want to execute a PUT request to update or replace a resource.` + +export interface Headers { + [key: string]: string +} + +export interface Body { + [key: string]: any +} + +export interface RequestParameters { + headers?: Headers + body?: Body + url?: string + description?: string + name?: string + bodySchema?: string + maxOutputLength?: number +} + +// Base schema for PUT request +const createRequestsPutSchema = (bodySchema?: string) => { + // If bodySchema is provided, parse it and add dynamic body params + if (bodySchema) { + try { + const parsedSchema = JSON.parse(bodySchema) + const bodyParamsObject: Record = {} + + Object.entries(parsedSchema).forEach(([key, config]: [string, any]) => { + let zodType: z.ZodTypeAny = z.string() + + // Handle different types + if (config.type === 'number') { + zodType = z.number() + } else if (config.type === 'boolean') { + zodType = z.boolean() + } else if (config.type === 'object') { + zodType = z.record(z.any()) + } else if (config.type === 'array') { + zodType = z.array(z.any()) + } + + // Add description + if (config.description) { + zodType = zodType.describe(config.description) + } + + // Make optional if not required + if (!config.required) { + zodType = zodType.optional() + } + + bodyParamsObject[key] = zodType + }) + + if (Object.keys(bodyParamsObject).length > 0) { + return z.object({ + body: z.object(bodyParamsObject).describe('Request body parameters') + }) + } + } catch (error) { + console.warn('Failed to parse bodySchema:', error) + } + } + + // Fallback to generic body + return z.object({ + body: z.record(z.any()).optional().describe('Optional body data to include in the request') + }) +} + +export class RequestsPutTool extends DynamicStructuredTool { + url = '' + maxOutputLength = Infinity + headers = {} + body = {} + bodySchema?: string + + constructor(args?: RequestParameters) { + const schema = createRequestsPutSchema(args?.bodySchema) + + const toolInput = { + name: args?.name || 'requests_put', + description: args?.description || desc, + schema: schema, + baseUrl: '', + method: 'PUT', + headers: args?.headers || {} + } + super(toolInput) + this.url = args?.url ?? this.url + this.headers = args?.headers ?? this.headers + this.body = args?.body ?? this.body + this.maxOutputLength = args?.maxOutputLength ?? this.maxOutputLength + this.bodySchema = args?.bodySchema + } + + /** @ignore */ + async _call(arg: any): Promise { + const params = { ...arg } + + try { + const inputUrl = this.url + if (!inputUrl) { + throw new Error('URL is required for PUT request') + } + + let inputBody = { + ...this.body + } + + if (this.bodySchema && params.body && Object.keys(params.body).length > 0) { + inputBody = { + ...inputBody, + ...params.body + } + } + + const requestHeaders = { + 'Content-Type': 'application/json', + ...(params.headers || {}), + ...this.headers + } + + const res = await fetch(inputUrl, { + method: 'PUT', + headers: requestHeaders, + body: JSON.stringify(inputBody) + }) + + if (!res.ok) { + throw new Error(`HTTP Error ${res.status}: ${res.statusText}`) + } + + const text = await res.text() + return text.slice(0, this.maxOutputLength) + } catch (error) { + throw new Error(`Failed to make PUT request: ${error instanceof Error ? error.message : 'Unknown error'}`) + } + } +} diff --git a/packages/components/nodes/tools/RequestsPut/put.png b/packages/components/nodes/tools/RequestsPut/put.png new file mode 100644 index 0000000000000000000000000000000000000000..f60c6f46b72bedf20f9f6560c50b40edf7e4472c GIT binary patch literal 9839 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 UewX;4kPJ#rN?Ec-+%)w60PPzIE&u=k literal 0 HcmV?d00001 diff --git a/packages/components/nodes/tools/StripeTool/stripe.png b/packages/components/nodes/tools/StripeTool/stripe.png index b73ff0db39593c87cbe4b450f58a24c3eeda9828..91867c7960a53934cdc68a977b950835f2a901a4 100644 GIT binary patch literal 9300 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

^BlHLYa6kP=iggF= zCu1eS^Enjr;Zza?NE!SJ;rob(xKh2A8@CW@f`*800hrR=m=K_;s;g3^Y#aXn0oF4d At^fc4 literal 69452 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 f=x+o3@gCmii2r%O;BMP_ct+e2i^I8x+ { const customURL = process.env.S3_ENDPOINT_URL const forcePathStyle = process.env.S3_FORCE_PATH_STYLE === 'true' ? true : false - if (!region || !Bucket) { + if (!region || region.trim() === '' || !Bucket || Bucket.trim() === '') { throw new Error('S3 storage configuration is missing') } const s3Config: S3ClientConfig = { region: region, - endpoint: customURL, forcePathStyle: forcePathStyle } - if (accessKeyId && secretAccessKey) { + // Only include endpoint if customURL is not empty + if (customURL && customURL.trim() !== '') { + s3Config.endpoint = customURL + } + + if (accessKeyId && accessKeyId.trim() !== '' && secretAccessKey && secretAccessKey.trim() !== '') { s3Config.credentials = { accessKeyId: accessKeyId, secretAccessKey: secretAccessKey diff --git a/packages/components/src/utils.ts b/packages/components/src/utils.ts index 5a62f93c..50d2465c 100644 --- a/packages/components/src/utils.ts +++ b/packages/components/src/utils.ts @@ -4,6 +4,7 @@ import * as fs from 'fs' import * as path from 'path' import { JSDOM } from 'jsdom' import { z } from 'zod' +import TurndownService from 'turndown' import { DataSource, Equal } from 'typeorm' import { ICommonObject, IDatabaseEntity, IFileUpload, IMessage, INodeData, IVariable, MessageContentImageUrl } from './Interface' import { AES, enc } from 'crypto-js' @@ -1309,3 +1310,11 @@ export const refreshOAuth2Token = async ( // Token is not expired, return original data return credentialData } + +export const stripHTMLFromToolInput = (input: string) => { + const turndownService = new TurndownService() + let cleanedInput = turndownService.turndown(input) + // After conversion, replace any escaped underscores with regular underscores + cleanedInput = cleanedInput.replace(/\\_/g, '_') + return cleanedInput +} diff --git a/packages/server/marketplaces/agentflowsv2/Agentic RAG V2.json b/packages/server/marketplaces/agentflowsv2/Agentic RAG.json similarity index 99% rename from packages/server/marketplaces/agentflowsv2/Agentic RAG V2.json rename to packages/server/marketplaces/agentflowsv2/Agentic RAG.json index c37df8a9..91131f51 100644 --- a/packages/server/marketplaces/agentflowsv2/Agentic RAG V2.json +++ b/packages/server/marketplaces/agentflowsv2/Agentic RAG.json @@ -1,6 +1,6 @@ { "description": "An agent based approach using AgentflowV2 to perform self-correcting question answering over documents", - "usecases": ["Reflective Agent"], + "usecases": ["Reflective Agent", "Documents QnA"], "nodes": [ { "id": "startAgentflow_0", diff --git a/packages/server/marketplaces/agentflowsv2/Deep Research V2.json b/packages/server/marketplaces/agentflowsv2/Deep Research With Multi-turn Conversations.json similarity index 98% rename from packages/server/marketplaces/agentflowsv2/Deep Research V2.json rename to packages/server/marketplaces/agentflowsv2/Deep Research With Multi-turn Conversations.json index bad7e2ef..21c4c256 100644 --- a/packages/server/marketplaces/agentflowsv2/Deep Research V2.json +++ b/packages/server/marketplaces/agentflowsv2/Deep Research With Multi-turn Conversations.json @@ -1,13 +1,13 @@ { - "description": "An agent capable of performing research, synthesizing information, and generating in-depth, well-structured white papers on any given topic", - "usecases": ["Agent"], + "description": "Deep research system that conducts multi-turn agent conversations to perform web search, synthesize insights and generate well-structured white papers", + "usecases": ["Deep Research"], "nodes": [ { "id": "startAgentflow_0", "type": "agentFlow", "position": { - "x": -275.0799323960054, - "y": 31.301887150099603 + "x": -397.64170181617976, + "y": 87.52288229696859 }, "data": { "id": "startAgentflow_0", @@ -188,19 +188,19 @@ "selected": false }, "width": 103, - "height": 65, + "height": 66, "selected": false, "positionAbsolute": { - "x": -275.0799323960054, - "y": 31.301887150099603 + "x": -397.64170181617976, + "y": 87.52288229696859 }, "dragging": false }, { "id": "llmAgentflow_0", "position": { - "x": -59.13383952997965, - "y": 28.495983624910906 + "x": -242.41428370877253, + "y": 85.84139867471725 }, "data": { "id": "llmAgentflow_0", @@ -513,19 +513,19 @@ }, "type": "agentFlow", "width": 175, - "height": 71, + "height": 72, "selected": false, "positionAbsolute": { - "x": -59.13383952997965, - "y": 28.495983624910906 + "x": -242.41428370877253, + "y": 85.84139867471725 }, "dragging": false }, { "id": "agentAgentflow_0", "position": { - "x": 209.99147630894493, - "y": 100.7933285478893 + "x": -26.136703307904796, + "y": 72.89650466398558 }, "data": { "id": "agentAgentflow_0", @@ -824,13 +824,6 @@ } ], "agentTools": [ - { - "agentSelectedTool": "braveSearchAPI", - "agentSelectedToolRequiresHumanInput": "", - "agentSelectedToolConfig": { - "agentSelectedTool": "braveSearchAPI" - } - }, { "agentSelectedTool": "webScraperTool", "agentSelectedToolRequiresHumanInput": "", @@ -842,6 +835,13 @@ "description": "", "agentSelectedTool": "webScraperTool" } + }, + { + "agentSelectedTool": "braveSearchAPI", + "agentSelectedToolRequiresHumanInput": "", + "agentSelectedToolConfig": { + "agentSelectedTool": "braveSearchAPI" + } } ], "agentKnowledgeDocumentStores": "", @@ -879,20 +879,20 @@ "selected": false }, "type": "agentFlow", - "width": 199, - "height": 103, + "width": 200, + "height": 100, "selected": false, "positionAbsolute": { - "x": 209.99147630894493, - "y": 100.7933285478893 + "x": -26.136703307904796, + "y": 72.89650466398558 }, "dragging": false }, { "id": "agentAgentflow_1", "position": { - "x": 203.50865583557328, - "y": -75.13070214403373 + "x": 210.25517525319754, + "y": 73.29272504370039 }, "data": { "id": "agentAgentflow_1", @@ -1191,13 +1191,6 @@ } ], "agentTools": [ - { - "agentSelectedTool": "braveSearchAPI", - "agentSelectedToolRequiresHumanInput": "", - "agentSelectedToolConfig": { - "agentSelectedTool": "braveSearchAPI" - } - }, { "agentSelectedTool": "webScraperTool", "agentSelectedToolRequiresHumanInput": "", @@ -1209,6 +1202,13 @@ "description": "", "agentSelectedTool": "webScraperTool" } + }, + { + "agentSelectedTool": "braveSearchAPI", + "agentSelectedToolRequiresHumanInput": "", + "agentSelectedToolConfig": { + "agentSelectedTool": "braveSearchAPI" + } } ], "agentKnowledgeDocumentStores": "", @@ -1246,24 +1246,24 @@ "selected": false }, "type": "agentFlow", - "width": 199, - "height": 103, + "width": 200, + "height": 100, "selected": false, "positionAbsolute": { - "x": 203.50865583557328, - "y": -75.13070214403373 + "x": 210.25517525319754, + "y": 73.29272504370039 }, "dragging": false }, { "id": "conditionAgentflow_0", "position": { - "x": 497.07879661792845, - "y": 29.068421396935392 + "x": 457.0277025649177, + "y": 83.6060813840138 }, "data": { "id": "conditionAgentflow_0", - "label": "Condition", + "label": "Check Iterations", "version": 1, "name": "conditionAgentflow", "type": "Condition", @@ -1520,24 +1520,24 @@ "selected": false }, "type": "agentFlow", - "width": 134, + "width": 178, "height": 80, "selected": false, "positionAbsolute": { - "x": 497.07879661792845, - "y": 29.068421396935392 + "x": 457.0277025649177, + "y": 83.6060813840138 }, "dragging": false }, { "id": "loopAgentflow_0", "position": { - "x": 710.6354115635097, - "y": -61.015932400168076 + "x": 690.1837890683553, + "y": 22.494859455045713 }, "data": { "id": "loopAgentflow_0", - "label": "Loop", + "label": "Loop Back to Agent 0", "version": 1, "name": "loopAgentflow", "type": "Loop", @@ -1575,13 +1575,13 @@ "selected": false }, "type": "agentFlow", - "width": 104, - "height": 65, + "width": 211, + "height": 66, "selected": false, "dragging": false, "positionAbsolute": { - "x": 710.6354115635097, - "y": -61.015932400168076 + "x": 690.1837890683553, + "y": 22.494859455045713 } }, { @@ -1900,8 +1900,8 @@ "selected": false }, "type": "agentFlow", - "width": 199, - "height": 71, + "width": 200, + "height": 72, "selected": false, "positionAbsolute": { "x": 693.0529196789191, @@ -1912,8 +1912,8 @@ { "id": "stickyNoteAgentflow_0", "position": { - "x": -320.62033146052283, - "y": -110.15285265313359 + "x": -445.43094068657194, + "y": -61.80279682682627 }, "data": { "id": "stickyNoteAgentflow_0", @@ -1952,20 +1952,20 @@ "selected": false }, "type": "stickyNote", - "width": 203, - "height": 122, + "width": 210, + "height": 123, "selected": false, "positionAbsolute": { - "x": -320.62033146052283, - "y": -110.15285265313359 + "x": -445.43094068657194, + "y": -61.80279682682627 }, "dragging": false }, { "id": "stickyNoteAgentflow_1", "position": { - "x": 466.8306744858025, - "y": -189.9009582021492 + "x": 454.90056136362915, + "y": -146.44126039994615 }, "data": { "id": "stickyNoteAgentflow_1", @@ -2004,12 +2004,12 @@ "selected": false }, "type": "stickyNote", - "width": 203, - "height": 202, + "width": 210, + "height": 203, "selected": false, "positionAbsolute": { - "x": 466.8306744858025, - "y": -189.9009582021492 + "x": 454.90056136362915, + "y": -146.44126039994615 }, "dragging": false }, @@ -2056,8 +2056,8 @@ "selected": false }, "type": "stickyNote", - "width": 203, - "height": 283, + "width": 210, + "height": 263, "selected": false, "positionAbsolute": { "x": 693.7511120802441, diff --git a/packages/server/marketplaces/agentflowsv2/Deep Research With Subagents.json b/packages/server/marketplaces/agentflowsv2/Deep Research With Subagents.json new file mode 100644 index 00000000..a8b32dad --- /dev/null +++ b/packages/server/marketplaces/agentflowsv2/Deep Research With Subagents.json @@ -0,0 +1,1831 @@ +{ + "description": "Multi-agent system that breaks down complex queries, assigns tasks to subagents, and synthesizes findings into detailed reports.", + "usecases": ["Deep Research"], + "nodes": [ + { + "id": "startAgentflow_0", + "type": "agentFlow", + "position": { + "x": -241.58365178492127, + "y": 86.32546838777353 + }, + "data": { + "id": "startAgentflow_0", + "label": "Start", + "version": 1.1, + "name": "startAgentflow", + "type": "Start", + "color": "#7EE787", + "hideInput": true, + "baseClasses": ["Start"], + "category": "Agent Flows", + "description": "Starting point of the agentflow", + "inputParams": [ + { + "label": "Input Type", + "name": "startInputType", + "type": "options", + "options": [ + { + "label": "Chat Input", + "name": "chatInput", + "description": "Start the conversation with chat input" + }, + { + "label": "Form Input", + "name": "formInput", + "description": "Start the workflow with form inputs" + } + ], + "default": "chatInput", + "id": "startAgentflow_0-input-startInputType-options", + "display": true + }, + { + "label": "Form Title", + "name": "formTitle", + "type": "string", + "placeholder": "Please Fill Out The Form", + "show": { + "startInputType": "formInput" + }, + "id": "startAgentflow_0-input-formTitle-string", + "display": true + }, + { + "label": "Form Description", + "name": "formDescription", + "type": "string", + "placeholder": "Complete all fields below to continue", + "show": { + "startInputType": "formInput" + }, + "id": "startAgentflow_0-input-formDescription-string", + "display": true + }, + { + "label": "Form Input Types", + "name": "formInputTypes", + "description": "Specify the type of form input", + "type": "array", + "show": { + "startInputType": "formInput" + }, + "array": [ + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Options", + "name": "options" + } + ], + "default": "string" + }, + { + "label": "Label", + "name": "label", + "type": "string", + "placeholder": "Label for the input" + }, + { + "label": "Variable Name", + "name": "name", + "type": "string", + "placeholder": "Variable name for the input (must be camel case)", + "description": "Variable name must be camel case. For example: firstName, lastName, etc." + }, + { + "label": "Add Options", + "name": "addOptions", + "type": "array", + "show": { + "formInputTypes[$index].type": "options" + }, + "array": [ + { + "label": "Option", + "name": "option", + "type": "string" + } + ] + } + ], + "id": "startAgentflow_0-input-formInputTypes-array", + "display": true + }, + { + "label": "Ephemeral Memory", + "name": "startEphemeralMemory", + "type": "boolean", + "description": "Start fresh for every execution without past chat history", + "optional": true + }, + { + "label": "Flow State", + "name": "startState", + "description": "Runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string", + "placeholder": "Foo" + }, + { + "label": "Value", + "name": "value", + "type": "string", + "placeholder": "Bar" + } + ], + "id": "startAgentflow_0-input-startState-array", + "display": true + }, + { + "label": "Persist State", + "name": "startPersistState", + "type": "boolean", + "description": "Persist the state in the same session", + "optional": true, + "id": "startAgentflow_0-input-startPersistState-boolean", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "startInputType": "formInput", + "formTitle": "Research", + "formDescription": "A research agent that takes in a query, and return a detailed report", + "formInputTypes": [ + { + "type": "string", + "label": "Query", + "name": "query", + "addOptions": "" + } + ], + "startState": [ + { + "key": "subagents", + "value": "" + }, + { + "key": "findings", + "value": "" + } + ] + }, + "outputAnchors": [ + { + "id": "startAgentflow_0-output-startAgentflow", + "label": "Start", + "name": "startAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "width": 103, + "height": 66, + "selected": false, + "positionAbsolute": { + "x": -241.58365178492127, + "y": 86.32546838777353 + }, + "dragging": false + }, + { + "id": "llmAgentflow_0", + "position": { + "x": -111.52635639216058, + "y": 83.67035986437665 + }, + "data": { + "id": "llmAgentflow_0", + "label": "Planner", + "version": 1, + "name": "llmAgentflow", + "type": "LLM", + "color": "#64B5F6", + "baseClasses": ["LLM"], + "category": "Agent Flows", + "description": "Large language models to analyze user-provided inputs and generate responses", + "inputParams": [ + { + "label": "Model", + "name": "llmModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "llmAgentflow_0-input-llmModel-asyncOptions", + "display": true + }, + { + "label": "Messages", + "name": "llmMessages", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Role", + "name": "role", + "type": "options", + "options": [ + { + "label": "System", + "name": "system" + }, + { + "label": "Assistant", + "name": "assistant" + }, + { + "label": "Developer", + "name": "developer" + }, + { + "label": "User", + "name": "user" + } + ] + }, + { + "label": "Content", + "name": "content", + "type": "string", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4 + } + ], + "id": "llmAgentflow_0-input-llmMessages-array", + "display": true + }, + { + "label": "Enable Memory", + "name": "llmEnableMemory", + "type": "boolean", + "description": "Enable memory for the conversation thread", + "default": true, + "optional": true, + "id": "llmAgentflow_0-input-llmEnableMemory-boolean", + "display": true + }, + { + "label": "Memory Type", + "name": "llmMemoryType", + "type": "options", + "options": [ + { + "label": "All Messages", + "name": "allMessages", + "description": "Retrieve all messages from the conversation" + }, + { + "label": "Window Size", + "name": "windowSize", + "description": "Uses a fixed window size to surface the last N messages" + }, + { + "label": "Conversation Summary", + "name": "conversationSummary", + "description": "Summarizes the whole conversation" + }, + { + "label": "Conversation Summary Buffer", + "name": "conversationSummaryBuffer", + "description": "Summarize conversations once token limit is reached. Default to 2000" + } + ], + "optional": true, + "default": "allMessages", + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_0-input-llmMemoryType-options", + "display": true + }, + { + "label": "Window Size", + "name": "llmMemoryWindowSize", + "type": "number", + "default": "20", + "description": "Uses a fixed window size to surface the last N messages", + "show": { + "llmMemoryType": "windowSize" + }, + "id": "llmAgentflow_0-input-llmMemoryWindowSize-number", + "display": false + }, + { + "label": "Max Token Limit", + "name": "llmMemoryMaxTokenLimit", + "type": "number", + "default": "2000", + "description": "Summarize conversations once token limit is reached. Default to 2000", + "show": { + "llmMemoryType": "conversationSummaryBuffer" + }, + "id": "llmAgentflow_0-input-llmMemoryMaxTokenLimit-number", + "display": false + }, + { + "label": "Input Message", + "name": "llmUserMessage", + "type": "string", + "description": "Add an input message as user message at the end of the conversation", + "rows": 4, + "optional": true, + "acceptVariable": true, + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_0-input-llmUserMessage-string", + "display": true + }, + { + "label": "Return Response As", + "name": "llmReturnResponseAs", + "type": "options", + "options": [ + { + "label": "User Message", + "name": "userMessage" + }, + { + "label": "Assistant Message", + "name": "assistantMessage" + } + ], + "default": "userMessage", + "id": "llmAgentflow_0-input-llmReturnResponseAs-options", + "display": true + }, + { + "label": "JSON Structured Output", + "name": "llmStructuredOutput", + "description": "Instruct the LLM to give output in a JSON structured schema", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string" + }, + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "String Array", + "name": "stringArray" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Enum", + "name": "enum" + }, + { + "label": "JSON Array", + "name": "jsonArray" + } + ] + }, + { + "label": "Enum Values", + "name": "enumValues", + "type": "string", + "placeholder": "value1, value2, value3", + "description": "Enum values. Separated by comma", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "enum" + } + }, + { + "label": "JSON Schema", + "name": "jsonSchema", + "type": "code", + "placeholder": "{\n \"answer\": {\n \"type\": \"string\",\n \"description\": \"Value of the answer\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"description\": \"Reason for the answer\"\n },\n \"optional\": {\n \"type\": \"boolean\"\n },\n \"count\": {\n \"type\": \"number\"\n },\n \"children\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\",\n \"description\": \"Value of the children's answer\"\n }\n }\n }\n }\n}", + "description": "JSON schema for the structured output", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "jsonArray" + } + }, + { + "label": "Description", + "name": "description", + "type": "string", + "placeholder": "Description of the key" + } + ], + "id": "llmAgentflow_0-input-llmStructuredOutput-array", + "display": true + }, + { + "label": "Update Flow State", + "name": "llmUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "llmAgentflow_0-input-llmUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "llmModel": "chatAnthropic", + "llmMessages": [ + { + "role": "system", + "content": "

You are an expert research lead, focused on high-level research strategy, planning, efficient delegation to subagents, and final report writing. Your core goal is to be maximally helpful to the user by leading a process to research the user's query and then creating an excellent research report that answers this query very well. Take the current request from the user, plan out an effective research process to answer it as well as possible, and then execute this plan by delegating key tasks to appropriate subagents.

The current date is {{ current_date_time }} .

<research_process>

Follow this process to break down the user’s question and develop an excellent research plan. Think about the user's task thoroughly and in great detail to understand it well and determine what to do next. Analyze each aspect of the user's question and identify the most important aspects. Consider multiple approaches with complete, thorough reasoning. Explore several different methods of answering the question (at least 3) and then choose the best method you find. Follow this process closely:

1. Assessment and breakdown: Analyze and break down the user's prompt to make sure you fully understand it.

* Identify the main concepts, key entities, and relationships in the task.

* List specific facts or data points needed to answer the question well.

* Note any temporal or contextual constraints on the question.

* Analyze what features of the prompt are most important - what does the user likely care about most here? What are they expecting or desiring in the final result? What tools do they expect to be used and how do we know?

* Determine what form the answer would need to be in to fully accomplish the user's task. Would it need to be a detailed report, a list of entities, an analysis of different perspectives, a visual report, or something else? What components will it need to have?

2. Query type determination: Explicitly state your reasoning on what type of query this question is from the categories below.

* Depth-first query: When the problem requires multiple perspectives on the same issue, and calls for \"going deep\" by analyzing a single topic from many angles.

- Benefits from parallel agents exploring different viewpoints, methodologies, or sources

- The core question remains singular but benefits from diverse approaches

- Example: \"What are the most effective treatments for depression?\" (benefits from parallel agents exploring different treatments and approaches to this question)

- Example: \"What really caused the 2008 financial crisis?\" (benefits from economic, regulatory, behavioral, and historical perspectives, and analyzing or steelmanning different viewpoints on the question)

- Example: \"can you identify the best approach to building AI finance agents in 2025 and why?\"

* Breadth-first query: When the problem can be broken into distinct, independent sub-questions, and calls for \"going wide\" by gathering information about each sub-question.

- Benefits from parallel agents each handling separate sub-topics.

- The query naturally divides into multiple parallel research streams or distinct, independently researchable sub-topics

- Example: \"Compare the economic systems of three Nordic countries\" (benefits from simultaneous independent research on each country)

- Example: \"What are the net worths and names of all the CEOs of all the fortune 500 companies?\" (intractable to research in a single thread; most efficient to split up into many distinct research agents which each gathers some of the necessary information)

- Example: \"Compare all the major frontend frameworks based on performance, learning curve, ecosystem, and industry adoption\" (best to identify all the frontend frameworks and then research all of these factors for each framework)

* Straightforward query: When the problem is focused, well-defined, and can be effectively answered by a single focused investigation or fetching a single resource from the internet.

- Can be handled effectively by a single subagent with clear instructions; does not benefit much from extensive research

- Example: \"What is the current population of Tokyo?\" (simple fact-finding)

- Example: \"What are all the fortune 500 companies?\" (just requires finding a single website with a full list, fetching that list, and then returning the results)

- Example: \"Tell me about bananas\" (fairly basic, short question that likely does not expect an extensive answer)

3. Detailed research plan development: Based on the query type, develop a specific research plan with clear allocation of tasks across different research subagents. Ensure if this plan is executed, it would result in an excellent answer to the user's query.

For Depth-first queries*:

- Define 3-5 different methodological approaches or perspectives.

- List specific expert viewpoints or sources of evidence that would enrich the analysis.

- Plan how each perspective will contribute unique insights to the central question.

- Specify how findings from different approaches will be synthesized.

- Example: For \"What causes obesity?\", plan agents to investigate genetic factors, environmental influences, psychological aspects, socioeconomic patterns, and biomedical evidence, and outline how the information could be aggregated into a great answer.

For Breadth-first queries*:

- Enumerate all the distinct sub-questions or sub-tasks that can be researched independently to answer the query.

- Identify the most critical sub-questions or perspectives needed to answer the query comprehensively. Only create additional subagents if the query has clearly distinct components that cannot be efficiently handled by fewer agents. Avoid creating subagents for every possible angle - focus on the essential ones.

- Prioritize these sub-tasks based on their importance and expected research complexity.

- Define extremely clear, crisp, and understandable boundaries between sub-topics to prevent overlap.

- Plan how findings will be aggregated into a coherent whole.

- Example: For \"Compare EU country tax systems\", first create a subagent to retrieve a list of all the countries in the EU today, then think about what metrics and factors would be relevant to compare each country's tax systems, then use the batch tool to run 4 subagents to research the metrics and factors for the key countries in Northern Europe, Western Europe, Eastern Europe, Southern Europe.

For Straightforward queries*:

- Identify the most direct, efficient path to the answer.

- Determine whether basic fact-finding or minor analysis is needed.

- Specify exact data points or information required to answer.

- Determine what sources are likely most relevant to answer this query that the subagents should use, and whether multiple sources are needed for fact-checking.

- Plan basic verification methods to ensure the accuracy of the answer.

- Create an extremely clear task description that describes how a subagent should research this question.

* For each element in your plan for answering any query, explicitly evaluate:

- Can this step be broken into independent subtasks for a more efficient process?

- Would multiple perspectives benefit this step?

- What specific output is expected from this step?

- Is this step strictly necessary to answer the user's query well?

4. Methodical plan execution: Execute the plan fully, using parallel subagents where possible. Determine how many subagents to use based on the complexity of the query, default to using 3 subagents for most queries.

* For parallelizable steps:

- Deploy appropriate subagents using the <delegation_instructions> below, making sure to provide extremely clear task descriptions to each subagent and ensuring that if these tasks are accomplished it would provide the information needed to answer the query.

- Synthesize findings when the subtasks are complete.

* For non-parallelizable/critical steps:

- First, attempt to accomplish them yourself based on your existing knowledge and reasoning. If the steps require additional research or up-to-date information from the web, deploy a subagent.

- If steps are very challenging, deploy independent subagents for additional perspectives or approaches.

- Compare the subagent's results and synthesize them using an ensemble approach and by applying critical reasoning.

* Throughout execution:

- Continuously monitor progress toward answering the user's query.

- Update the search plan and your subagent delegation strategy based on findings from tasks.

- Adapt to new information well - analyze the results, use Bayesian reasoning to update your priors, and then think carefully about what to do next.

- Adjust research depth based on time constraints and efficiency - if you are running out of time or a research process has already taken a very long time, avoid deploying further subagents and instead just start composing the output report immediately.

</research_process>

<subagent_count_guidelines>

When determining how many subagents to create, follow these guidelines:

1. Simple/Straightforward queries: create 1 subagent to collaborate with you directly -

- Example: \"What is the tax deadline this year?\" or “Research bananas” → 1 subagent

- Even for simple queries, always create at least 1 subagent to ensure proper source gathering

2. Standard complexity queries: 2-3 subagents

- For queries requiring multiple perspectives or research approaches

- Example: \"Compare the top 3 cloud providers\" → 3 subagents (one per provider)

3. Medium complexity queries: 3-5 subagents

- For multi-faceted questions requiring different methodological approaches

- Example: \"Analyze the impact of AI on healthcare\" → 4 subagents (regulatory, clinical, economic, technological aspects)

4. High complexity queries: 5-10 subagents (maximum 20)

- For very broad, multi-part queries with many distinct components

- Identify the most effective algorithms to efficiently answer these high-complexity queries with around 20 subagents.

- Example: \"Fortune 500 CEOs birthplaces and ages\" → Divide the large info-gathering task into smaller segments (e.g., 10 subagents handling 50 CEOs each)

IMPORTANT: Never create more than 20 subagents unless strictly necessary. If a task seems to require more than 20 subagents, it typically means you should restructure your approach to consolidate similar sub-tasks and be more efficient in your research process. Prefer fewer, more capable subagents over many overly narrow ones. More subagents = more overhead. Only add subagents when they provide distinct value.

</subagent_count_guidelines>

<delegation_instructions>

Use subagents as your primary research team - they should perform all major research tasks:

1. Deployment strategy:

* Deploy subagents immediately after finalizing your research plan, so you can start the research process quickly.

* Create research subagent with very clear and specific instructions to describe the subagent's task.

* Each subagent is a fully capable researcher that can search the web and use the other search tools that are available.

* Consider priority and dependency when ordering subagent tasks - deploy the most important subagents first. For instance, when other tasks will depend on results from one specific task, always create a subagent to address that blocking task first.

* Ensure you have sufficient coverage for comprehensive research - ensure that you deploy subagents to complete every task.

* All substantial information gathering should be delegated to subagents.

* While waiting for a subagent to complete, use your time efficiently by analyzing previous results, updating your research plan, or reasoning about the user's query and how to answer it best.

2. Task allocation principles:

* For depth-first queries: Deploy subagents in sequence to explore different methodologies or perspectives on the same core question. Start with the approach most likely to yield comprehensive and good results, the follow with alternative viewpoints to fill gaps or provide contrasting analysis.

* For breadth-first queries: Order subagents by topic importance and research complexity. Begin with subagents that will establish key facts or framework information, then deploy subsequent subagents to explore more specific or dependent subtopics.

* For straightforward queries: Deploy a single comprehensive subagent with clear instructions for fact-finding and verification. For these simple queries, treat the subagent as an equal collaborator - you can conduct some research yourself while delegating specific research tasks to the subagent. Give this subagent very clear instructions and try to ensure the subagent handles about half of the work, to efficiently distribute research work between yourself and the subagent.

* Avoid deploying subagents for trivial tasks that you can complete yourself, such as simple calculations, basic formatting, small web searches, or tasks that don't require external research

* But always deploy at least 1 subagent, even for simple tasks.

* Avoid overlap between subagents - every subagent should have distinct, clearly separate tasks, to avoid replicating work unnecessarily and wasting resources.

3. Clear direction for subagents: Ensure that you provide every subagent with extremely detailed, specific, and clear instructions for what their task is and how to accomplish it.

* All instructions for subagents should include the following as appropriate:

- Specific research objectives, ideally just 1 core objective per subagent.

- Expected output format - e.g. a list of entities, a report of the facts, an answer to a specific question, or other.

- Relevant background context about the user's question and how the subagent should contribute to the research plan.

- Key questions to answer as part of the research.

- Suggested starting points and sources to use; define what constitutes reliable information or high-quality sources for this task, and list any unreliable sources to avoid.

- Specific tools that the subagent should use - i.e. using web search and web fetch for gathering information from the web, or if the query requires non-public, company-specific, or user-specific information, use the available internal tools like google drive, gmail, gcal, slack, or any other internal tools that are available currently.

- If needed, precise scope boundaries to prevent research drift.

* Make sure that IF all the subagents followed their instructions very well, the results in aggregate would allow you to give an EXCELLENT answer to the user's question - complete, thorough, detailed, and accurate.

* When giving instructions to subagents, also think about what sources might be high-quality for their tasks, and give them some guidelines on what sources to use and how they should evaluate source quality for each task.

* Example of a good, clear, detailed task description for a subagent: \"Research the semiconductor supply chain crisis and its current status as of 2025. Use the web_search and web_fetch tools to gather facts from the internet. Begin by examining recent quarterly reports from major chip manufacturers like TSMC, Samsung, and Intel, which can be found on their investor relations pages or through the SEC EDGAR database. Search for industry reports from SEMI, Gartner, and IDC that provide market analysis and forecasts. Investigate government responses by checking the US CHIPS Act implementation progress at commerce.gov, EU Chips Act at ec.europa.eu, and similar initiatives in Japan, South Korea, and Taiwan through their respective government portals. Prioritize original sources over news aggregators. Focus on identifying current bottlenecks, projected capacity increases from new fab construction, geopolitical factors affecting supply chains, and expert predictions for when supply will meet demand. When research is done, compile your findings into a dense report of the facts, covering the current situation, ongoing solutions, and future outlook, with specific timelines and quantitative data where available.\"

4. Synthesis responsibility: As the lead research agent, your primary role is to coordinate, guide, and synthesize - NOT to conduct primary research yourself. You only conduct direct research if a critical question remains unaddressed by subagents or it is best to accomplish it yourself. Instead, focus on planning, analyzing and integrating findings across subagents, determining what to do next, providing clear instructions for each subagent, or identifying gaps in the collective research and deploying new subagents to fill them.

</delegation_instructions>

<answer_formatting>

Before providing a final answer:

1. Review the most recent fact list compiled during the search process.

2. Reflect deeply on whether these facts can answer the given query sufficiently.

3. Identify if you need to create more subagents for further research.

4. If sufficient, provide a final answer in the specific format that is best for the user's query and following the <writing_guidelines> below.

4. Output the final result in Markdown to submit your final research report.

5. Do not include ANY Markdown citations, a separate agent will be responsible for citations. Never include a list of references or sources or citations at the end of the report.

</answer_formatting>

In communicating with subagents, maintain extremely high information density while being concise - describe everything needed in the fewest words possible.

As you progress through the search process:

1. When necessary, review the core facts gathered so far, including: f

* Facts from your own research.

* Facts reported by subagents.

* Specific dates, numbers, and quantifiable data.

2. For key facts, especially numbers, dates, and critical information:

* Note any discrepancies you observe between sources or issues with the quality of sources.

* When encountering conflicting information, prioritize based on recency, consistency with other facts, and use best judgment.

3. Think carefully after receiving novel information, especially for critical reasoning and decision-making after getting results back from subagents.

4. For the sake of efficiency, when you have reached the point where further research has diminishing returns and you can give a good enough answer to the user, STOP FURTHER RESEARCH and do not create any new subagents. Just write your final report at this point. Make sure to terminate research when it is no longer necessary, to avoid wasting time and resources. For example, if you are asked to identify the top 5 fastest-growing startups, and you have identified the most likely top 5 startups with high confidence, stop research immediately and use the complete_task tool to submit your report rather than continuing the process unnecessarily.

5. NEVER create a subagent to generate the final report - YOU write and craft this final research report yourself based on all the results and the writing instructions, and you are never allowed to use subagents to create the report.

6. Avoid creating subagents to research topics that could cause harm. Specifically, you must not create subagents to research anything that would promote hate speech, racism, violence, discrimination, or catastrophic harm. If a query is sensitive, specify clear constraints for the subagent to avoid causing harm.

</important_guidelines>

You have a query provided to you by the user, which serves as your primary goal. You should do your best to thoroughly accomplish the user's task. No clarifications will be given, therefore use your best judgment and do not attempt to ask the user questions. Before starting your work, review these instructions and the user’s requirements, making sure to plan out how you will efficiently use subagents and parallel tool calls to answer the query. Critically think about the results provided by subagents and reason about them carefully to verify information and ensure you provide a high-quality, accurate report. Accomplish the user’s task by directing the research subagents and creating an excellent research report from the information gathered.

" + }, + { + "role": "user", + "content": "

Query:

{{ $form.query }}

" + } + ], + "llmEnableMemory": true, + "llmReturnResponseAs": "userMessage", + "llmStructuredOutput": [ + { + "key": "subagents", + "type": "jsonArray", + "enumValues": "", + "jsonSchema": "{\n \"task\": {\n \"type\": \"string\",\n \"description\": \"The research task for subagent\"\n }\n}", + "description": "A list of subagents to perform research task" + } + ], + "llmUpdateState": [ + { + "key": "subagents", + "value": "

{{ output.subagents }}

" + } + ], + "llmModelConfig": { + "credential": "", + "modelName": "claude-sonnet-4-0", + "temperature": 0.9, + "streaming": true, + "maxTokensToSample": "", + "topP": "", + "topK": "", + "extendedThinking": "", + "budgetTokens": 1024, + "allowImageUploads": "", + "llmModel": "chatAnthropic" + }, + "llmUserMessage": "

" + }, + "outputAnchors": [ + { + "id": "llmAgentflow_0-output-llmAgentflow", + "label": "LLM", + "name": "llmAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 213, + "height": 72, + "selected": false, + "positionAbsolute": { + "x": -111.52635639216058, + "y": 83.67035986437665 + }, + "dragging": false + }, + { + "id": "iterationAgentflow_0", + "position": { + "x": 126.70987564816664, + "y": -5.337791594648138 + }, + "data": { + "id": "iterationAgentflow_0", + "label": "Spawn SubAgents", + "version": 1, + "name": "iterationAgentflow", + "type": "Iteration", + "color": "#9C89B8", + "baseClasses": ["Iteration"], + "category": "Agent Flows", + "description": "Execute the nodes within the iteration block through N iterations", + "inputParams": [ + { + "label": "Array Input", + "name": "iterationInput", + "type": "string", + "description": "The input array to iterate over", + "acceptVariable": true, + "rows": 4, + "id": "iterationAgentflow_0-input-iterationInput-string", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "iterationInput": "

{{ $flow.state.subagents }}

" + }, + "outputAnchors": [ + { + "id": "iterationAgentflow_0-output-iterationAgentflow", + "label": "Iteration", + "name": "iterationAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "iteration", + "width": 300, + "height": 250, + "selected": false, + "positionAbsolute": { + "x": 126.70987564816664, + "y": -5.337791594648138 + }, + "dragging": false + }, + { + "id": "agentAgentflow_0", + "position": { + "x": 53.64516693688461, + "y": 77.49272566017132 + }, + "data": { + "id": "agentAgentflow_0", + "label": "SubAgent", + "version": 1, + "name": "agentAgentflow", + "type": "Agent", + "color": "#4DD0E1", + "baseClasses": ["Agent"], + "category": "Agent Flows", + "description": "Dynamically choose and utilize tools during runtime, enabling multi-step reasoning", + "inputParams": [ + { + "label": "Model", + "name": "agentModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "agentAgentflow_0-input-agentModel-asyncOptions", + "display": true + }, + { + "label": "Messages", + "name": "agentMessages", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Role", + "name": "role", + "type": "options", + "options": [ + { + "label": "System", + "name": "system" + }, + { + "label": "Assistant", + "name": "assistant" + }, + { + "label": "Developer", + "name": "developer" + }, + { + "label": "User", + "name": "user" + } + ] + }, + { + "label": "Content", + "name": "content", + "type": "string", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4 + } + ], + "id": "agentAgentflow_0-input-agentMessages-array", + "display": true + }, + { + "label": "Tools", + "name": "agentTools", + "type": "array", + "optional": true, + "array": [ + { + "label": "Tool", + "name": "agentSelectedTool", + "type": "asyncOptions", + "loadMethod": "listTools", + "loadConfig": true + }, + { + "label": "Require Human Input", + "name": "agentSelectedToolRequiresHumanInput", + "type": "boolean", + "optional": true + } + ], + "id": "agentAgentflow_0-input-agentTools-array", + "display": true + }, + { + "label": "Knowledge (Document Stores)", + "name": "agentKnowledgeDocumentStores", + "type": "array", + "description": "Give your agent context about different document sources. Document stores must be upserted in advance.", + "array": [ + { + "label": "Document Store", + "name": "documentStore", + "type": "asyncOptions", + "loadMethod": "listStores" + }, + { + "label": "Describe Knowledge", + "name": "docStoreDescription", + "type": "string", + "generateDocStoreDescription": true, + "placeholder": "Describe what the knowledge base is about, this is useful for the AI to know when and how to search for correct information", + "rows": 4 + }, + { + "label": "Return Source Documents", + "name": "returnSourceDocuments", + "type": "boolean", + "optional": true + } + ], + "optional": true, + "id": "agentAgentflow_0-input-agentKnowledgeDocumentStores-array", + "display": true + }, + { + "label": "Knowledge (Vector Embeddings)", + "name": "agentKnowledgeVSEmbeddings", + "type": "array", + "description": "Give your agent context about different document sources from existing vector stores and embeddings", + "array": [ + { + "label": "Vector Store", + "name": "vectorStore", + "type": "asyncOptions", + "loadMethod": "listVectorStores", + "loadConfig": true + }, + { + "label": "Embedding Model", + "name": "embeddingModel", + "type": "asyncOptions", + "loadMethod": "listEmbeddings", + "loadConfig": true + }, + { + "label": "Knowledge Name", + "name": "knowledgeName", + "type": "string", + "placeholder": "A short name for the knowledge base, this is useful for the AI to know when and how to search for correct information" + }, + { + "label": "Describe Knowledge", + "name": "knowledgeDescription", + "type": "string", + "placeholder": "Describe what the knowledge base is about, this is useful for the AI to know when and how to search for correct information", + "rows": 4 + }, + { + "label": "Return Source Documents", + "name": "returnSourceDocuments", + "type": "boolean", + "optional": true + } + ], + "optional": true, + "id": "agentAgentflow_0-input-agentKnowledgeVSEmbeddings-array", + "display": true + }, + { + "label": "Enable Memory", + "name": "agentEnableMemory", + "type": "boolean", + "description": "Enable memory for the conversation thread", + "default": true, + "optional": true, + "id": "agentAgentflow_0-input-agentEnableMemory-boolean", + "display": true + }, + { + "label": "Memory Type", + "name": "agentMemoryType", + "type": "options", + "options": [ + { + "label": "All Messages", + "name": "allMessages", + "description": "Retrieve all messages from the conversation" + }, + { + "label": "Window Size", + "name": "windowSize", + "description": "Uses a fixed window size to surface the last N messages" + }, + { + "label": "Conversation Summary", + "name": "conversationSummary", + "description": "Summarizes the whole conversation" + }, + { + "label": "Conversation Summary Buffer", + "name": "conversationSummaryBuffer", + "description": "Summarize conversations once token limit is reached. Default to 2000" + } + ], + "optional": true, + "default": "allMessages", + "show": { + "agentEnableMemory": true + }, + "id": "agentAgentflow_0-input-agentMemoryType-options", + "display": true + }, + { + "label": "Window Size", + "name": "agentMemoryWindowSize", + "type": "number", + "default": "20", + "description": "Uses a fixed window size to surface the last N messages", + "show": { + "agentMemoryType": "windowSize" + }, + "id": "agentAgentflow_0-input-agentMemoryWindowSize-number", + "display": false + }, + { + "label": "Max Token Limit", + "name": "agentMemoryMaxTokenLimit", + "type": "number", + "default": "2000", + "description": "Summarize conversations once token limit is reached. Default to 2000", + "show": { + "agentMemoryType": "conversationSummaryBuffer" + }, + "id": "agentAgentflow_0-input-agentMemoryMaxTokenLimit-number", + "display": false + }, + { + "label": "Input Message", + "name": "agentUserMessage", + "type": "string", + "description": "Add an input message as user message at the end of the conversation", + "rows": 4, + "optional": true, + "acceptVariable": true, + "show": { + "agentEnableMemory": true + }, + "id": "agentAgentflow_0-input-agentUserMessage-string", + "display": true + }, + { + "label": "Return Response As", + "name": "agentReturnResponseAs", + "type": "options", + "options": [ + { + "label": "User Message", + "name": "userMessage" + }, + { + "label": "Assistant Message", + "name": "assistantMessage" + } + ], + "default": "userMessage", + "id": "agentAgentflow_0-input-agentReturnResponseAs-options", + "display": true + }, + { + "label": "Update Flow State", + "name": "agentUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "agentAgentflow_0-input-agentUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "agentModel": "chatAnthropic", + "agentMessages": [ + { + "role": "system", + "content": "

You are a research subagent working as part of a team. The current date is {{ current_date_time }}. You have been given a clear <task> provided by a lead agent, and should use your available tools to accomplish this task in a research process. Follow the instructions below closely to accomplish your specific <task> well:

<task>

{{ $iteration.task }}

</task>

<research_process>

  1. Planning: First, think through the task thoroughly. Make a research plan, carefully reasoning to review the requirements of the task, develop a research plan to fulfill these requirements, and determine what tools are most relevant and how they should be used optimally to fulfill the task.

  • As part of the plan, determine a 'research budget' - roughly how many tool calls to conduct to accomplish this task. Adapt the number of tool calls to the complexity of the query to be maximally efficient. For instance, simpler tasks like \"when is the tax deadline this year\" should result in under 5 tool calls, medium tasks should result in 5 tool calls, hard tasks result in about 10 tool calls, and very difficult or multi-part tasks should result in up to 15 tool calls. Stick to this budget to remain efficient - going over will hit your limits!

  1. Tool selection: Reason about what tools would be most helpful to use for this task. Use the right tools when a task implies they would be helpful.

  • Use BraveSearch API to research the topic, especially looking for different perspectives, counter-arguments, or aspects Agent 0 might not have covered. Identify URLs that seem promising for more detail.

  • If a URL from BraveSearch API (or one you already know) seems particularly important for your point or for adding nuance, use the Web Scraper Tool to get its full content.

  • Use Arxiv Search Tool for getting arxiv papers and contents.

  1. Research loop: Execute an excellent OODA (observe, orient, decide, act) loop by (a) observing what information has been gathered so far, what still needs to be gathered to accomplish the task, and what tools are available currently; (b) orienting toward what tools and queries would be best to gather the needed information and updating beliefs based on what has been learned so far; (c) making an informed, well-reasoned decision to use a specific tool in a certain way; (d) acting to use this tool. Repeat this loop in an efficient way to research well and learn based on new results.

  • Execute a MINIMUM of two distinct tool calls, up to five for complex queries. Avoid using more than five tool calls.

  • Reason carefully after receiving tool results. Make inferences based on each tool result and determine which tools to use next based on new findings in this process - e.g. if it seems like some info is not available on the web or some approach is not working, try using another tool or another query. Evaluate the quality of the sources in search results carefully. NEVER repeatedly use the exact same queries for the same tools, as this wastes resources and will not return new results.

Follow this process well to complete the task. Make sure to follow the <task> description and investigate the best sources.

</research_process>

<research_guidelines>

  1. Be detailed in your internal process, but more concise and information-dense in reporting the results.

  2. Avoid overly specific searches that might have poor hit rates:

    • Use moderately broad queries rather than hyper-specific ones.

    • Keep queries shorter since this will return more useful results - under 5 words.

    • If specific searches yield few results, broaden slightly.

    • Adjust specificity based on result quality - if results are abundant, narrow the query to get specific information.

    • Find the right balance between specific and general.

  3. For important facts, especially numbers and dates:

    • Keep track of findings and sources

    • Focus on high-value information that is:

    • Significant (has major implications for the task)

    • Important (directly relevant to the task or specifically requested)

    • Precise (specific facts, numbers, dates, or other concrete information)

    • High-quality (from excellent, reputable, reliable sources for the task)

* When encountering conflicting information, prioritize based on recency, consistency with other facts, the quality of the sources used, and use your best judgment and reasoning. If unable to reconcile facts, include the conflicting information in your final task report for the lead researcher to resolve.

4. Be specific and precise in your information gathering approach.

</research_guidelines>

<think_about_source_quality>

After receiving results from web searches or other tools, think critically, reason about the results, and determine what to do next. Pay attention to the details of tool results, and do not just take them at face value. For example, some pages may speculate about things that may happen in the future - mentioning predictions, using verbs like “could” or “may”, narrative driven speculation with future tense, quoted superlatives, financial projections, or similar - and you should make sure to note this explicitly in the final report, rather than accepting these events as having happened. Similarly, pay attention to the indicators of potentially problematic sources, like news aggregators rather than original sources of the information, false authority, pairing of passive voice with nameless sources, general qualifiers without specifics, unconfirmed reports, marketing language for a product, spin language, speculation, or misleading and cherry-picked data. Maintain epistemic honesty and practice good reasoning by ensuring sources are high-quality and only reporting accurate information to the lead researcher. If there are potential issues with results, flag these issues when returning your report to the lead researcher rather than blindly presenting all results as established facts.

DO NOT use the evaluate_source_quality tool ever - ignore this tool. It is broken and using it will not work.

</think_about_source_quality>

<use_parallel_tool_calls>

For maximum efficiency, whenever you need to perform multiple independent operations, invoke 2 relevant tools simultaneously rather than sequentially. Prefer calling tools like web search in parallel rather than by themselves.

</use_parallel_tool_calls>

<maximum_tool_call_limit>

To prevent overloading the system, it is required that you stay under a limit of 5 tool calls and under about 10 sources. This is the absolute maximum upper limit. If you exceed this limit, the subagent will be terminated. Therefore, whenever you get to around 4 tool calls or 9 sources, make sure to stop gathering sources, and instead finish it immediately. Avoid continuing to use tools when you see diminishing returns - when you are no longer finding new relevant information and results are not getting better, STOP using tools and instead compose your final report.

</maximum_tool_call_limit>

<citations>

  1. Must include source link, pages, etc.

  2. Avoid citing unnecessarily: Not every statement needs a citation. Focus on citing key facts, conclusions, and substantive claims that are linked to sources rather than common knowledge. Prioritize citing claims that readers would want to verify, that add credibility to the argument, or where a claim is clearly related to a specific source

  3. Cite meaningful semantic units: Citations should span complete thoughts, findings, or claims that make sense as standalone assertions. Avoid citing individual words or small phrase fragments that lose meaning out of context; prefer adding citations at the end of sentences

  4. Minimize sentence fragmentation: Avoid multiple citations within a single sentence that break up the flow of the sentence. Only add citations between phrases within a sentence when it is necessary to attribute specific claims within the sentence to specific sources

  5. No redundant citations close to each other: Do not place multiple citations to the same source in the same sentence, because this is redundant and unnecessary. If a sentence contains multiple citable claims from the same source, use only a single citation at the end of the sentence after the period

</citations>

Follow the <research_process> and the <research_guidelines> above to accomplish the task, making sure to parallelize tool calls for maximum efficiency. Remember to use correct tool to retrieve full results rather than just using search snippets. Continue using the relevant tools until this task has been fully accomplished, all necessary information has been gathered, and you are ready to report the results to the lead research agent to be integrated into a final result. As soon as you have the necessary information, complete the task rather than wasting time by continuing research unnecessarily. As soon as the task is done, finish and provide your detailed, condensed, complete, accurate report with citations.

" + } + ], + "agentTools": [ + { + "agentSelectedTool": "arxiv", + "agentSelectedToolRequiresHumanInput": "", + "agentSelectedToolConfig": { + "arxivName": "arxiv_search", + "arxivDescription": "Use this tool to search for academic papers on Arxiv. You can search by keywords, topics, authors, or specific Arxiv IDs. The tool can return either paper summaries or download and extract full paper content.", + "topKResults": "3", + "maxQueryLength": "300", + "docContentCharsMax": "5000", + "loadFullContent": true, + "continueOnFailure": true, + "legacyBuild": "", + "agentSelectedTool": "arxiv" + } + }, + { + "agentSelectedTool": "googleCustomSearch", + "agentSelectedToolRequiresHumanInput": "", + "agentSelectedToolConfig": { + "credential": "", + "agentSelectedTool": "googleCustomSearch" + } + }, + { + "agentSelectedTool": "webScraperTool", + "agentSelectedToolRequiresHumanInput": "", + "agentSelectedToolConfig": { + "scrapeMode": "recursive", + "maxDepth": 1, + "maxPages": "2", + "timeoutS": 60, + "description": "", + "agentSelectedTool": "webScraperTool" + } + } + ], + "agentKnowledgeDocumentStores": "", + "agentEnableMemory": true, + "agentMemoryType": "allMessages", + "agentUserMessage": "

Research task:

{{ $iteration.task }}

", + "agentReturnResponseAs": "userMessage", + "agentUpdateState": "", + "agentModelConfig": { + "credential": "", + "modelName": "claude-sonnet-4-0", + "temperature": 0.9, + "streaming": true, + "maxTokensToSample": "", + "topP": "", + "topK": "", + "extendedThinking": "", + "budgetTokens": 1024, + "allowImageUploads": "", + "agentModel": "chatAnthropic" + } + }, + "outputAnchors": [ + { + "id": "agentAgentflow_0-output-agentAgentflow", + "label": "Agent", + "name": "agentAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "parentNode": "iterationAgentflow_0", + "extent": "parent", + "width": 213, + "height": 100, + "selected": false, + "positionAbsolute": { + "x": 180.35504258505125, + "y": 72.15493406552318 + }, + "dragging": false + }, + { + "id": "agentAgentflow_1", + "position": { + "x": 457.5784259377066, + "y": 83.96506302841382 + }, + "data": { + "id": "agentAgentflow_1", + "label": "Writer Agent", + "version": 1, + "name": "agentAgentflow", + "type": "Agent", + "color": "#4DD0E1", + "baseClasses": ["Agent"], + "category": "Agent Flows", + "description": "Dynamically choose and utilize tools during runtime, enabling multi-step reasoning", + "inputParams": [ + { + "label": "Model", + "name": "agentModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "agentAgentflow_1-input-agentModel-asyncOptions", + "display": true + }, + { + "label": "Messages", + "name": "agentMessages", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Role", + "name": "role", + "type": "options", + "options": [ + { + "label": "System", + "name": "system" + }, + { + "label": "Assistant", + "name": "assistant" + }, + { + "label": "Developer", + "name": "developer" + }, + { + "label": "User", + "name": "user" + } + ] + }, + { + "label": "Content", + "name": "content", + "type": "string", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4 + } + ], + "id": "agentAgentflow_1-input-agentMessages-array", + "display": true + }, + { + "label": "Tools", + "name": "agentTools", + "type": "array", + "optional": true, + "array": [ + { + "label": "Tool", + "name": "agentSelectedTool", + "type": "asyncOptions", + "loadMethod": "listTools", + "loadConfig": true + }, + { + "label": "Require Human Input", + "name": "agentSelectedToolRequiresHumanInput", + "type": "boolean", + "optional": true + } + ], + "id": "agentAgentflow_1-input-agentTools-array", + "display": true + }, + { + "label": "Knowledge (Document Stores)", + "name": "agentKnowledgeDocumentStores", + "type": "array", + "description": "Give your agent context about different document sources. Document stores must be upserted in advance.", + "array": [ + { + "label": "Document Store", + "name": "documentStore", + "type": "asyncOptions", + "loadMethod": "listStores" + }, + { + "label": "Describe Knowledge", + "name": "docStoreDescription", + "type": "string", + "generateDocStoreDescription": true, + "placeholder": "Describe what the knowledge base is about, this is useful for the AI to know when and how to search for correct information", + "rows": 4 + }, + { + "label": "Return Source Documents", + "name": "returnSourceDocuments", + "type": "boolean", + "optional": true + } + ], + "optional": true, + "id": "agentAgentflow_1-input-agentKnowledgeDocumentStores-array", + "display": true + }, + { + "label": "Knowledge (Vector Embeddings)", + "name": "agentKnowledgeVSEmbeddings", + "type": "array", + "description": "Give your agent context about different document sources from existing vector stores and embeddings", + "array": [ + { + "label": "Vector Store", + "name": "vectorStore", + "type": "asyncOptions", + "loadMethod": "listVectorStores", + "loadConfig": true + }, + { + "label": "Embedding Model", + "name": "embeddingModel", + "type": "asyncOptions", + "loadMethod": "listEmbeddings", + "loadConfig": true + }, + { + "label": "Knowledge Name", + "name": "knowledgeName", + "type": "string", + "placeholder": "A short name for the knowledge base, this is useful for the AI to know when and how to search for correct information" + }, + { + "label": "Describe Knowledge", + "name": "knowledgeDescription", + "type": "string", + "placeholder": "Describe what the knowledge base is about, this is useful for the AI to know when and how to search for correct information", + "rows": 4 + }, + { + "label": "Return Source Documents", + "name": "returnSourceDocuments", + "type": "boolean", + "optional": true + } + ], + "optional": true, + "id": "agentAgentflow_1-input-agentKnowledgeVSEmbeddings-array", + "display": true + }, + { + "label": "Enable Memory", + "name": "agentEnableMemory", + "type": "boolean", + "description": "Enable memory for the conversation thread", + "default": true, + "optional": true, + "id": "agentAgentflow_1-input-agentEnableMemory-boolean", + "display": true + }, + { + "label": "Memory Type", + "name": "agentMemoryType", + "type": "options", + "options": [ + { + "label": "All Messages", + "name": "allMessages", + "description": "Retrieve all messages from the conversation" + }, + { + "label": "Window Size", + "name": "windowSize", + "description": "Uses a fixed window size to surface the last N messages" + }, + { + "label": "Conversation Summary", + "name": "conversationSummary", + "description": "Summarizes the whole conversation" + }, + { + "label": "Conversation Summary Buffer", + "name": "conversationSummaryBuffer", + "description": "Summarize conversations once token limit is reached. Default to 2000" + } + ], + "optional": true, + "default": "allMessages", + "show": { + "agentEnableMemory": true + }, + "id": "agentAgentflow_1-input-agentMemoryType-options", + "display": false + }, + { + "label": "Window Size", + "name": "agentMemoryWindowSize", + "type": "number", + "default": "20", + "description": "Uses a fixed window size to surface the last N messages", + "show": { + "agentMemoryType": "windowSize" + }, + "id": "agentAgentflow_1-input-agentMemoryWindowSize-number", + "display": false + }, + { + "label": "Max Token Limit", + "name": "agentMemoryMaxTokenLimit", + "type": "number", + "default": "2000", + "description": "Summarize conversations once token limit is reached. Default to 2000", + "show": { + "agentMemoryType": "conversationSummaryBuffer" + }, + "id": "agentAgentflow_1-input-agentMemoryMaxTokenLimit-number", + "display": false + }, + { + "label": "Input Message", + "name": "agentUserMessage", + "type": "string", + "description": "Add an input message as user message at the end of the conversation", + "rows": 4, + "optional": true, + "acceptVariable": true, + "show": { + "agentEnableMemory": true + }, + "id": "agentAgentflow_1-input-agentUserMessage-string", + "display": false + }, + { + "label": "Return Response As", + "name": "agentReturnResponseAs", + "type": "options", + "options": [ + { + "label": "User Message", + "name": "userMessage" + }, + { + "label": "Assistant Message", + "name": "assistantMessage" + } + ], + "default": "userMessage", + "id": "agentAgentflow_1-input-agentReturnResponseAs-options", + "display": true + }, + { + "label": "Update Flow State", + "name": "agentUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "agentAgentflow_1-input-agentUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "agentModel": "chatGoogleGenerativeAI", + "agentMessages": [ + { + "role": "system", + "content": "

You are an expert research writer tasked with generating a high-quality, long-form Markdown report based on raw research findings. Your primary responsibility is to transform complex, fragmented, or unstructured research inputs into a coherent, professional report that fully answers the user's original query. This report should be suitable for audience seeking a deep understanding of the subject.

Your guiding principles:

  1. Preserve Full Context
    Include all relevant findings, explanations, and perspectives from the original materials. Do not omit, summarize, or oversimplify key information. Your job is to retain depth and nuance while improving structure and clarity.

  2. Maintain Citation Integrity
    Ensure all citations and source links from the original findings are accurately preserved in the final report. Do not invent, remove, or alter sources. If citations are embedded inline in the source findings, carry them forward appropriately.

  3. Add Structure and Clarity
    Organize the content into a well-structured Markdown format. Use clear section headings, bullet points, numbered lists, tables and formatting as needed to improve readability and flow. Start with Introduction, end with Conclusion, and lastly sources.

  4. Markdown Output Only
    Your final output must be in Markdown format. Do not include explanations, side notes, or appendices. The only output should be the fully composed report ready for submission.

Writing guidelines:

  1. Title: A clear, compelling title for the report that reflects the core subject.

  2. Abstract/Executive Summary: A concise overview (approx. 200-300 words) of the report main arguments, scope, and conclusions, derived from the conversation.

  3. Introduction:

    • Clearly define the central problem, question, or theme that the report will address

    • Outline the report's structure and objectives.

  4. Main Body / Thematic Analysis (Multiple Sections):

    • Deconstruct and Synthesize Key Arguments: Detail the principal arguments, propositions, and evidence presented by all findings. Go beyond mere listing; analyze the strengths, weaknesses, and underlying assumptions of their positions.

    • Explore Core Themes and Concepts: Identify and elaborate on the major themes and concepts that emerged.

    • Analyze the Evolution of the Discussion: Trace how the understanding of the subject evolved throughout the findings. Highlight any shifts in perspective, critical turning points, challenged assumptions, or moments of significant clarification.

    • Evidence and Examples: Where the findings provided examples or evidence, incorporate and potentially expand upon these to support the report's analysis.

  5. Synthesis of Insights and Key Conclusions:

    • Draw together the most significant insights and conclusions that can be derived from the entirety of the conversation.

    • This section should offer a consolidated understanding of the subject.

  6. Implications and Future Directions:

    • Discuss the broader implications of the insights and conclusions reached.

    • Identify any unresolved questions, ambiguities, or areas that the conversation indicated require further exploration or research.

    • Suggest potential next steps or future avenues of inquiry.

  7. Conclusion: A strong concluding section summarizing the report's main findings, their significance, and a final thought on the subject.

Style and Tone:

  • Extensive and In-depth: The paper should be thorough and detailed.

  • Well-Structured: Use clear headings, subheadings, and logical flow.

  • Analytical and Critical: Do not just report; analyze, interpret, and critically engage with the ideas.

  • Objective and Authoritative: The report should present a balanced and well-reasoned perspective.

  • Formal and Professional Language: Maintain a tone appropriate for the report.

" + }, + { + "role": "user", + "content": "

<research_topic>

{{ $form.query }}

</research_topic>

<existing_findings>

{{ $flow.state.findings }}

</existing_findings>

<new_findings>

{{ iterationAgentflow_0 }}

</new_findings>

" + } + ], + "agentTools": "", + "agentKnowledgeDocumentStores": "", + "agentEnableMemory": false, + "agentReturnResponseAs": "userMessage", + "agentUpdateState": [ + { + "key": "findings", + "value": "

{{ output }}

" + } + ], + "agentModelConfig": { + "credential": "", + "modelName": "gemini-2.5-flash-preview-05-20", + "customModelName": "", + "temperature": 0.9, + "streaming": true, + "maxOutputTokens": "", + "topP": "", + "topK": "", + "harmCategory": "", + "harmBlockThreshold": "", + "baseUrl": "", + "allowImageUploads": "", + "agentModel": "chatGoogleGenerativeAI" + }, + "undefined": "" + }, + "outputAnchors": [ + { + "id": "agentAgentflow_1-output-agentAgentflow", + "label": "Agent", + "name": "agentAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 284, + "height": 72, + "selected": false, + "positionAbsolute": { + "x": 457.5784259377066, + "y": 83.96506302841382 + }, + "dragging": false + }, + { + "id": "stickyNoteAgentflow_0", + "position": { + "x": 186.43721235573946, + "y": -175.0715078328168 + }, + "data": { + "id": "stickyNoteAgentflow_0", + "label": "Sticky Note", + "version": 1, + "name": "stickyNoteAgentflow", + "type": "StickyNote", + "color": "#fee440", + "baseClasses": ["StickyNote"], + "category": "Agent Flows", + "description": "Add notes to the agent flow", + "inputParams": [ + { + "label": "", + "name": "note", + "type": "string", + "rows": 1, + "placeholder": "Type something here", + "optional": true, + "id": "stickyNoteAgentflow_0-input-note-string", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "note": "Each SubAgent has its own research task and tools to complete its findings" + }, + "outputAnchors": [ + { + "id": "stickyNoteAgentflow_0-output-stickyNoteAgentflow", + "label": "Sticky Note", + "name": "stickyNoteAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "stickyNote", + "width": 210, + "height": 123, + "selected": false, + "positionAbsolute": { + "x": 186.43721235573946, + "y": -175.0715078328168 + }, + "dragging": false + }, + { + "id": "stickyNoteAgentflow_1", + "position": { + "x": -117.00547059767304, + "y": -24.08438212240118 + }, + "data": { + "id": "stickyNoteAgentflow_1", + "label": "Sticky Note (1)", + "version": 1, + "name": "stickyNoteAgentflow", + "type": "StickyNote", + "color": "#fee440", + "baseClasses": ["StickyNote"], + "category": "Agent Flows", + "description": "Add notes to the agent flow", + "inputParams": [ + { + "label": "", + "name": "note", + "type": "string", + "rows": 1, + "placeholder": "Type something here", + "optional": true, + "id": "stickyNoteAgentflow_1-input-note-string", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "note": "Planner will generate list of subagents" + }, + "outputAnchors": [ + { + "id": "stickyNoteAgentflow_1-output-stickyNoteAgentflow", + "label": "Sticky Note", + "name": "stickyNoteAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "stickyNote", + "width": 210, + "height": 82, + "selected": false, + "positionAbsolute": { + "x": -117.00547059767304, + "y": -24.08438212240118 + }, + "dragging": false + }, + { + "id": "conditionAgentAgentflow_0", + "position": { + "x": 775.5108094609307, + "y": 79.60273632963377 + }, + "data": { + "id": "conditionAgentAgentflow_0", + "label": "More SubAgents?", + "version": 1.1, + "name": "conditionAgentAgentflow", + "type": "ConditionAgent", + "color": "#ff8fab", + "baseClasses": ["ConditionAgent"], + "category": "Agent Flows", + "description": "Utilize an agent to split flows based on dynamic conditions", + "inputParams": [ + { + "label": "Model", + "name": "conditionAgentModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "conditionAgentAgentflow_0-input-conditionAgentModel-asyncOptions", + "display": true + }, + { + "label": "Instructions", + "name": "conditionAgentInstructions", + "type": "string", + "description": "A general instructions of what the condition agent should do", + "rows": 4, + "acceptVariable": true, + "placeholder": "Determine if the user is interested in learning about AI", + "id": "conditionAgentAgentflow_0-input-conditionAgentInstructions-string", + "display": true + }, + { + "label": "Input", + "name": "conditionAgentInput", + "type": "string", + "description": "Input to be used for the condition agent", + "rows": 4, + "acceptVariable": true, + "default": "

{{ question }}

", + "id": "conditionAgentAgentflow_0-input-conditionAgentInput-string", + "display": true + }, + { + "label": "Scenarios", + "name": "conditionAgentScenarios", + "description": "Define the scenarios that will be used as the conditions to split the flow", + "type": "array", + "array": [ + { + "label": "Scenario", + "name": "scenario", + "type": "string", + "placeholder": "User is asking for a pizza" + } + ], + "default": [ + { + "scenario": "More subagents needed" + }, + { + "scenario": "It is sufficient" + } + ], + "id": "conditionAgentAgentflow_0-input-conditionAgentScenarios-array", + "display": true + }, + { + "label": "Override System Prompt", + "name": "conditionAgentOverrideSystemPrompt", + "type": "boolean", + "description": "Override initial system prompt for Condition Agent", + "optional": true, + "id": "conditionAgentAgentflow_0-input-conditionAgentOverrideSystemPrompt-boolean", + "display": true + }, + { + "label": "Node System Prompt", + "name": "conditionAgentSystemPrompt", + "type": "string", + "rows": 4, + "optional": true, + "acceptVariable": true, + "default": "

You are part of a multi-agent system designed to make agent coordination and execution easy. Your task is to analyze the given input and select one matching scenario from a provided set of scenarios.

\n
    \n
  • Input: A string representing the user's query, message or data.
  • \n
  • Scenarios: A list of predefined scenarios that relate to the input.
  • \n
  • Instruction: Determine which of the provided scenarios is the best fit for the input.
  • \n
\n

Steps

\n
    \n
  1. Read the input string and the list of scenarios.
  2. \n
  3. Analyze the content of the input to identify its main topic or intention.
  4. \n
  5. Compare the input with each scenario: Evaluate how well the input's topic or intention aligns with each of the provided scenarios and select the one that is the best fit.
  6. \n
  7. Output the result: Return the selected scenario in the specified JSON format.
  8. \n
\n

Output Format

\n

Output should be a JSON object that names the selected scenario, like this: {\"output\": \"\"}. No explanation is needed.

\n

Examples

\n
    \n
  1. \n

    Input: {\"input\": \"Hello\", \"scenarios\": [\"user is asking about AI\", \"user is not asking about AI\"], \"instruction\": \"Your task is to check if the user is asking about AI.\"}

    \n

    Output: {\"output\": \"user is not asking about AI\"}

    \n
  2. \n
  3. \n

    Input: {\"input\": \"What is AIGC?\", \"scenarios\": [\"user is asking about AI\", \"user is asking about the weather\"], \"instruction\": \"Your task is to check and see if the user is asking a topic about AI.\"}

    \n

    Output: {\"output\": \"user is asking about AI\"}

    \n
  4. \n
  5. \n

    Input: {\"input\": \"Can you explain deep learning?\", \"scenarios\": [\"user is interested in AI topics\", \"user wants to order food\"], \"instruction\": \"Determine if the user is interested in learning about AI.\"}

    \n

    Output: {\"output\": \"user is interested in AI topics\"}

    \n
  6. \n
\n

Note

\n
    \n
  • Ensure that the input scenarios align well with potential user queries for accurate matching.
  • \n
  • DO NOT include anything other than the JSON in your response.
  • \n
", + "description": "Expert use only. Modifying this can significantly alter agent behavior. Leave default if unsure", + "show": { + "conditionAgentOverrideSystemPrompt": true + }, + "id": "conditionAgentAgentflow_0-input-conditionAgentSystemPrompt-string", + "display": false + } + ], + "inputAnchors": [], + "inputs": { + "conditionAgentModel": "chatGoogleGenerativeAI", + "conditionAgentInstructions": "

Given a research topic, previous subagents and their findings, determine if more subagents are needed for further research or the findings are sufficient for the research topic

", + "conditionAgentInput": "

<research_topic>

{{ $form.query }}

</research_topic>

<subagents>

{{ $flow.state.subagents }}

</subagents>

<findings>

{{ $flow.state.findings }}

</findings>

", + "conditionAgentScenarios": [ + { + "scenario": "More subagents are needed" + }, + { + "scenario": "Findings are sufficient" + } + ], + "conditionAgentOverrideSystemPrompt": "", + "conditionAgentModelConfig": { + "credential": "", + "modelName": "gemini-2.0-flash-lite", + "customModelName": "", + "temperature": 0.9, + "streaming": true, + "maxOutputTokens": "", + "topP": "", + "topK": "", + "harmCategory": "", + "harmBlockThreshold": "", + "baseUrl": "", + "allowImageUploads": "", + "conditionAgentModel": "chatGoogleGenerativeAI" + }, + "undefined": "" + }, + "outputAnchors": [ + { + "id": "conditionAgentAgentflow_0-output-0", + "label": "Condition Agent", + "name": "conditionAgentAgentflow" + }, + { + "id": "conditionAgentAgentflow_0-output-1", + "label": "Condition Agent", + "name": "conditionAgentAgentflow" + } + ], + "outputs": { + "conditionAgentAgentflow": "" + }, + "selected": false + }, + "type": "agentFlow", + "width": 220, + "height": 80, + "selected": false, + "positionAbsolute": { + "x": 775.5108094609307, + "y": 79.60273632963377 + }, + "dragging": false + }, + { + "id": "loopAgentflow_0", + "position": { + "x": 1041.3074957535728, + "y": 20.713295322365383 + }, + "data": { + "id": "loopAgentflow_0", + "label": "Back to Planner", + "version": 1, + "name": "loopAgentflow", + "type": "Loop", + "color": "#FFA07A", + "hideOutput": true, + "baseClasses": ["Loop"], + "category": "Agent Flows", + "description": "Loop back to a previous node", + "inputParams": [ + { + "label": "Loop Back To", + "name": "loopBackToNode", + "type": "asyncOptions", + "loadMethod": "listPreviousNodes", + "freeSolo": true, + "id": "loopAgentflow_0-input-loopBackToNode-asyncOptions", + "display": true + }, + { + "label": "Max Loop Count", + "name": "maxLoopCount", + "type": "number", + "default": 5, + "id": "loopAgentflow_0-input-maxLoopCount-number", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "loopBackToNode": "llmAgentflow_0-Planner", + "maxLoopCount": "5" + }, + "outputAnchors": [], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 174, + "height": 66, + "selected": false, + "positionAbsolute": { + "x": 1041.3074957535728, + "y": 20.713295322365383 + }, + "dragging": false + }, + { + "id": "directReplyAgentflow_0", + "position": { + "x": 1046.735958385286, + "y": 140.25100072990062 + }, + "data": { + "id": "directReplyAgentflow_0", + "label": "Generate Report", + "version": 1, + "name": "directReplyAgentflow", + "type": "DirectReply", + "color": "#4DDBBB", + "hideOutput": true, + "baseClasses": ["DirectReply"], + "category": "Agent Flows", + "description": "Directly reply to the user with a message", + "inputParams": [ + { + "label": "Message", + "name": "directReplyMessage", + "type": "string", + "rows": 4, + "acceptVariable": true, + "id": "directReplyAgentflow_0-input-directReplyMessage-string", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "directReplyMessage": "

{{ $flow.state.findings }}

" + }, + "outputAnchors": [], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 179, + "height": 66, + "positionAbsolute": { + "x": 1046.735958385286, + "y": 140.25100072990062 + }, + "selected": false, + "dragging": false + }, + { + "id": "stickyNoteAgentflow_3", + "position": { + "x": 494.1635881448354, + "y": -47.5842428829507 + }, + "data": { + "id": "stickyNoteAgentflow_3", + "label": "Sticky Note (3)", + "version": 1, + "name": "stickyNoteAgentflow", + "type": "StickyNote", + "color": "#fee440", + "baseClasses": ["StickyNote"], + "category": "Agent Flows", + "description": "Add notes to the agent flow", + "inputParams": [ + { + "label": "", + "name": "note", + "type": "string", + "rows": 1, + "placeholder": "Type something here", + "optional": true, + "id": "stickyNoteAgentflow_3-input-note-string", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "note": "Write Agent combine the findings and generate an updated report" + }, + "outputAnchors": [ + { + "id": "stickyNoteAgentflow_3-output-stickyNoteAgentflow", + "label": "Sticky Note", + "name": "stickyNoteAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "stickyNote", + "width": 210, + "height": 123, + "selected": false, + "positionAbsolute": { + "x": 494.1635881448354, + "y": -47.5842428829507 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "startAgentflow_0", + "sourceHandle": "startAgentflow_0-output-startAgentflow", + "target": "llmAgentflow_0", + "targetHandle": "llmAgentflow_0", + "data": { + "sourceColor": "#7EE787", + "targetColor": "#64B5F6", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "startAgentflow_0-startAgentflow_0-output-startAgentflow-llmAgentflow_0-llmAgentflow_0" + }, + { + "source": "llmAgentflow_0", + "sourceHandle": "llmAgentflow_0-output-llmAgentflow", + "target": "iterationAgentflow_0", + "targetHandle": "iterationAgentflow_0", + "data": { + "sourceColor": "#64B5F6", + "targetColor": "#9C89B8", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "llmAgentflow_0-llmAgentflow_0-output-llmAgentflow-iterationAgentflow_0-iterationAgentflow_0" + }, + { + "source": "conditionAgentAgentflow_0", + "sourceHandle": "conditionAgentAgentflow_0-output-0", + "target": "loopAgentflow_0", + "targetHandle": "loopAgentflow_0", + "data": { + "sourceColor": "#ff8fab", + "targetColor": "#FFA07A", + "edgeLabel": "0", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "conditionAgentAgentflow_0-conditionAgentAgentflow_0-output-0-loopAgentflow_0-loopAgentflow_0" + }, + { + "source": "iterationAgentflow_0", + "sourceHandle": "iterationAgentflow_0-output-iterationAgentflow", + "target": "agentAgentflow_1", + "targetHandle": "agentAgentflow_1", + "data": { + "sourceColor": "#9C89B8", + "targetColor": "#4DD0E1", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "iterationAgentflow_0-iterationAgentflow_0-output-iterationAgentflow-agentAgentflow_1-agentAgentflow_1" + }, + { + "source": "agentAgentflow_1", + "sourceHandle": "agentAgentflow_1-output-agentAgentflow", + "target": "conditionAgentAgentflow_0", + "targetHandle": "conditionAgentAgentflow_0", + "data": { + "sourceColor": "#4DD0E1", + "targetColor": "#ff8fab", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "agentAgentflow_1-agentAgentflow_1-output-agentAgentflow-conditionAgentAgentflow_0-conditionAgentAgentflow_0" + }, + { + "source": "conditionAgentAgentflow_0", + "sourceHandle": "conditionAgentAgentflow_0-output-1", + "target": "directReplyAgentflow_0", + "targetHandle": "directReplyAgentflow_0", + "data": { + "sourceColor": "#ff8fab", + "targetColor": "#4DDBBB", + "edgeLabel": "1", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "conditionAgentAgentflow_0-conditionAgentAgentflow_0-output-1-directReplyAgentflow_0-directReplyAgentflow_0" + } + ] +} diff --git a/packages/server/marketplaces/agentflowsv2/Financial Research Agent.json b/packages/server/marketplaces/agentflowsv2/Human In The Loop.json similarity index 67% rename from packages/server/marketplaces/agentflowsv2/Financial Research Agent.json rename to packages/server/marketplaces/agentflowsv2/Human In The Loop.json index ac4dab53..17bd719c 100644 --- a/packages/server/marketplaces/agentflowsv2/Financial Research Agent.json +++ b/packages/server/marketplaces/agentflowsv2/Human In The Loop.json @@ -1,13 +1,13 @@ { - "description": "A financial research agent that takes in a query, plan the steps, search the web, and return a detailed report", - "usecases": ["Finance & Accounting"], + "description": "An email reply HITL (human in the loop) agent that can proceed or refine the email with user input", + "usecases": ["Human In Loop"], "nodes": [ { "id": "startAgentflow_0", "type": "agentFlow", "position": { - "x": -234.94624728418063, - "y": 84.92919739582129 + "x": -201.62473061824977, + "y": 92.61621373702832 }, "data": { "id": "startAgentflow_0", @@ -133,7 +133,8 @@ "name": "startEphemeralMemory", "type": "boolean", "description": "Start fresh for every execution without past chat history", - "optional": true + "optional": true, + "display": true }, { "label": "Flow State", @@ -171,22 +172,29 @@ "inputAnchors": [], "inputs": { "startInputType": "formInput", - "formTitle": "Finanical Research", - "formDescription": "A financial research agent that takes in a query, and return a detailed report", + "formTitle": "Email Inquiry", + "formDescription": "Incoming email inquiry", "formInputTypes": [ { "type": "string", - "label": "Query", - "name": "query", + "label": "Subject", + "name": "subject", + "addOptions": "" + }, + { + "type": "string", + "label": "Body", + "name": "body", + "addOptions": "" + }, + { + "type": "string", + "label": "From", + "name": "from", "addOptions": "" } ], - "startState": [ - { - "key": "search_key_reason", - "value": "" - } - ] + "startState": "" }, "outputAnchors": [ { @@ -198,419 +206,24 @@ "outputs": {}, "selected": false }, - "width": 101, - "height": 65, + "width": 103, + "height": 66, "selected": false, "positionAbsolute": { - "x": -234.94624728418063, - "y": 84.92919739582129 - }, - "dragging": false - }, - { - "id": "llmAgentflow_0", - "position": { - "x": -92.42002168895628, - "y": 81.69973969492588 - }, - "data": { - "id": "llmAgentflow_0", - "label": "Planner", - "version": 1, - "name": "llmAgentflow", - "type": "LLM", - "color": "#64B5F6", - "baseClasses": ["LLM"], - "category": "Agent Flows", - "description": "Large language models to analyze user-provided inputs and generate responses", - "inputParams": [ - { - "label": "Model", - "name": "llmModel", - "type": "asyncOptions", - "loadMethod": "listModels", - "loadConfig": true, - "id": "llmAgentflow_0-input-llmModel-asyncOptions", - "display": true - }, - { - "label": "Messages", - "name": "llmMessages", - "type": "array", - "optional": true, - "acceptVariable": true, - "array": [ - { - "label": "Role", - "name": "role", - "type": "options", - "options": [ - { - "label": "System", - "name": "system" - }, - { - "label": "Assistant", - "name": "assistant" - }, - { - "label": "Developer", - "name": "developer" - }, - { - "label": "User", - "name": "user" - } - ] - }, - { - "label": "Content", - "name": "content", - "type": "string", - "acceptVariable": true, - "generateInstruction": true, - "rows": 4 - } - ], - "id": "llmAgentflow_0-input-llmMessages-array", - "display": true - }, - { - "label": "Enable Memory", - "name": "llmEnableMemory", - "type": "boolean", - "description": "Enable memory for the conversation thread", - "default": true, - "optional": true, - "id": "llmAgentflow_0-input-llmEnableMemory-boolean", - "display": true - }, - { - "label": "Memory Type", - "name": "llmMemoryType", - "type": "options", - "options": [ - { - "label": "All Messages", - "name": "allMessages", - "description": "Retrieve all messages from the conversation" - }, - { - "label": "Window Size", - "name": "windowSize", - "description": "Uses a fixed window size to surface the last N messages" - }, - { - "label": "Conversation Summary", - "name": "conversationSummary", - "description": "Summarizes the whole conversation" - }, - { - "label": "Conversation Summary Buffer", - "name": "conversationSummaryBuffer", - "description": "Summarize conversations once token limit is reached. Default to 2000" - } - ], - "optional": true, - "default": "allMessages", - "show": { - "llmEnableMemory": true - }, - "id": "llmAgentflow_0-input-llmMemoryType-options", - "display": true - }, - { - "label": "Window Size", - "name": "llmMemoryWindowSize", - "type": "number", - "default": "20", - "description": "Uses a fixed window size to surface the last N messages", - "show": { - "llmMemoryType": "windowSize" - }, - "id": "llmAgentflow_0-input-llmMemoryWindowSize-number", - "display": false - }, - { - "label": "Max Token Limit", - "name": "llmMemoryMaxTokenLimit", - "type": "number", - "default": "2000", - "description": "Summarize conversations once token limit is reached. Default to 2000", - "show": { - "llmMemoryType": "conversationSummaryBuffer" - }, - "id": "llmAgentflow_0-input-llmMemoryMaxTokenLimit-number", - "display": false - }, - { - "label": "Input Message", - "name": "llmUserMessage", - "type": "string", - "description": "Add an input message as user message at the end of the conversation", - "rows": 4, - "optional": true, - "acceptVariable": true, - "show": { - "llmEnableMemory": true - }, - "id": "llmAgentflow_0-input-llmUserMessage-string", - "display": true - }, - { - "label": "Return Response As", - "name": "llmReturnResponseAs", - "type": "options", - "options": [ - { - "label": "User Message", - "name": "userMessage" - }, - { - "label": "Assistant Message", - "name": "assistantMessage" - } - ], - "default": "userMessage", - "id": "llmAgentflow_0-input-llmReturnResponseAs-options", - "display": true - }, - { - "label": "JSON Structured Output", - "name": "llmStructuredOutput", - "description": "Instruct the LLM to give output in a JSON structured schema", - "type": "array", - "optional": true, - "acceptVariable": true, - "array": [ - { - "label": "Key", - "name": "key", - "type": "string" - }, - { - "label": "Type", - "name": "type", - "type": "options", - "options": [ - { - "label": "String", - "name": "string" - }, - { - "label": "String Array", - "name": "stringArray" - }, - { - "label": "Number", - "name": "number" - }, - { - "label": "Boolean", - "name": "boolean" - }, - { - "label": "Enum", - "name": "enum" - }, - { - "label": "JSON Array", - "name": "jsonArray" - } - ] - }, - { - "label": "Enum Values", - "name": "enumValues", - "type": "string", - "placeholder": "value1, value2, value3", - "description": "Enum values. Separated by comma", - "optional": true, - "show": { - "llmStructuredOutput[$index].type": "enum" - } - }, - { - "label": "JSON Schema", - "name": "jsonSchema", - "type": "code", - "placeholder": "{\n \"answer\": {\n \"type\": \"string\",\n \"description\": \"Value of the answer\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"description\": \"Reason for the answer\"\n },\n \"optional\": {\n \"type\": \"boolean\"\n },\n \"count\": {\n \"type\": \"number\"\n },\n \"children\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\",\n \"description\": \"Value of the children's answer\"\n }\n }\n }\n }\n}", - "description": "JSON schema for the structured output", - "optional": true, - "show": { - "llmStructuredOutput[$index].type": "jsonArray" - } - }, - { - "label": "Description", - "name": "description", - "type": "string", - "placeholder": "Description of the key" - } - ], - "id": "llmAgentflow_0-input-llmStructuredOutput-array", - "display": true - }, - { - "label": "Update Flow State", - "name": "llmUpdateState", - "description": "Update runtime state during the execution of the workflow", - "type": "array", - "optional": true, - "acceptVariable": true, - "array": [ - { - "label": "Key", - "name": "key", - "type": "asyncOptions", - "loadMethod": "listRuntimeStateKeys", - "freeSolo": true - }, - { - "label": "Value", - "name": "value", - "type": "string", - "acceptVariable": true, - "acceptNodeOutputAsVariable": true - } - ], - "id": "llmAgentflow_0-input-llmUpdateState-array", - "display": true - } - ], - "inputAnchors": [], - "inputs": { - "llmModel": "chatOpenAI", - "llmMessages": [ - { - "role": "system", - "content": "

You are a financial research planner. Given a request for financial analysis, produce a set of web searches to gather the context needed. Aim for recent headlines, earnings calls or 10‑K snippets, analyst commentary, and industry background. Output between 1 and 2 search terms to query for.

" - }, - { - "role": "user", - "content": "

Query:

{{ $form.query }}

" - } - ], - "llmEnableMemory": true, - "llmReturnResponseAs": "userMessage", - "llmStructuredOutput": [ - { - "key": "searches", - "type": "jsonArray", - "enumValues": "", - "jsonSchema": "{\n \"query\": {\n \"type\": \"string\",\n \"description\": \"The search term to feed into a web (or file) search.\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"description\": \"Your reasoning for why this search is relevant.\"\n }\n}", - "description": "A list of searches to perform" - } - ], - "llmUpdateState": [ - { - "key": "search_key_reason", - "value": "

{{ output.searches }}

" - } - ], - "llmModelConfig": { - "cache": "", - "modelName": "gpt-4o-mini", - "temperature": 0.9, - "streaming": true, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "strictToolCalling": "", - "stopSequence": "", - "basepath": "", - "proxyUrl": "", - "baseOptions": "", - "allowImageUploads": "", - "imageResolution": "low", - "reasoningEffort": "medium", - "llmModel": "chatOpenAI" - }, - "llmUserMessage": "

" - }, - "outputAnchors": [ - { - "id": "llmAgentflow_0-output-llmAgentflow", - "label": "LLM", - "name": "llmAgentflow" - } - ], - "outputs": {}, - "selected": false - }, - "type": "agentFlow", - "width": 168, - "height": 71, - "selected": false, - "positionAbsolute": { - "x": -92.42002168895628, - "y": 81.69973969492588 - }, - "dragging": false - }, - { - "id": "iterationAgentflow_0", - "position": { - "x": 122.70987564816664, - "y": -7.337791594648152 - }, - "data": { - "id": "iterationAgentflow_0", - "label": "Iteration 0", - "version": 1, - "name": "iterationAgentflow", - "type": "Iteration", - "color": "#9C89B8", - "baseClasses": ["Iteration"], - "category": "Agent Flows", - "description": "Execute the nodes within the iteration block through N iterations", - "inputParams": [ - { - "label": "Array Input", - "name": "iterationInput", - "type": "string", - "description": "The input array to iterate over", - "acceptVariable": true, - "rows": 4, - "id": "iterationAgentflow_0-input-iterationInput-string", - "display": true - } - ], - "inputAnchors": [], - "inputs": { - "iterationInput": "

{{ $flow.state.search_key_reason }}

" - }, - "outputAnchors": [ - { - "id": "iterationAgentflow_0-output-iterationAgentflow", - "label": "Iteration", - "name": "iterationAgentflow" - } - ], - "outputs": {}, - "selected": false - }, - "type": "iteration", - "width": 300, - "height": 250, - "selected": false, - "positionAbsolute": { - "x": 122.70987564816664, - "y": -7.337791594648152 + "x": -201.62473061824977, + "y": 92.61621373702832 }, "dragging": false }, { "id": "agentAgentflow_0", "position": { - "x": 67.5, - "y": 80.5 + "x": -61.56009223078007, + "y": 76 }, "data": { "id": "agentAgentflow_0", - "label": "Search Agent", + "label": "Email Reply Agent", "version": 1, "name": "agentAgentflow", "type": "Agent", @@ -901,7 +514,7 @@ "agentMessages": [ { "role": "system", - "content": "

You are a research assistant specializing in financial topics. Given a search term, use web search to retrieve up‑to‑date context and produce a short summary of at most 300 words. Focus on key numbers, events, or quotes that will be useful to a financial analyst.

" + "content": "

You are a customer support agent working in Flowise Inc. Write a professional email reply to user's query. Use the web search tools to get more details about the prospect.

Always reply as Samantha, Customer Support Representative in Flowise. Dont use placeholders.

" } ], "agentTools": [ @@ -910,12 +523,18 @@ "agentSelectedToolConfig": { "agentSelectedTool": "googleCustomSearch" } + }, + { + "agentSelectedTool": "currentDateTime", + "agentSelectedToolConfig": { + "agentSelectedTool": "currentDateTime" + } } ], "agentKnowledgeDocumentStores": "", "agentEnableMemory": true, "agentMemoryType": "allMessages", - "agentUserMessage": "

Search term: {{$iteration.query}}

Reason: {{$iteration.reason}}

", + "agentUserMessage": "", "agentReturnResponseAs": "userMessage", "agentUpdateState": "", "agentModelConfig": { @@ -950,46 +569,361 @@ "selected": false }, "type": "agentFlow", - "parentNode": "iterationAgentflow_0", - "extent": "parent", - "width": 168, - "height": 103, + "width": 189, + "height": 100, "selected": false, "positionAbsolute": { - "x": 190.20987564816664, - "y": 73.16220840535185 + "x": -61.56009223078007, + "y": 76 }, "dragging": false }, { - "id": "agentAgentflow_1", + "id": "humanInputAgentflow_0", "position": { - "x": 461.76351005035474, - "y": 81.71183989476083 + "x": 156.05666363734434, + "y": 86.62266545493773 }, "data": { - "id": "agentAgentflow_1", - "label": "Writer Agent", + "id": "humanInputAgentflow_0", + "label": "Human Input 0", "version": 1, - "name": "agentAgentflow", - "type": "Agent", - "color": "#4DD0E1", - "baseClasses": ["Agent"], + "name": "humanInputAgentflow", + "type": "HumanInput", + "color": "#6E6EFD", + "baseClasses": ["HumanInput"], "category": "Agent Flows", - "description": "Dynamically choose and utilize tools during runtime, enabling multi-step reasoning", + "description": "Request human input, approval or rejection during execution", "inputParams": [ + { + "label": "Description Type", + "name": "humanInputDescriptionType", + "type": "options", + "options": [ + { + "label": "Fixed", + "name": "fixed", + "description": "Specify a fixed description" + }, + { + "label": "Dynamic", + "name": "dynamic", + "description": "Use LLM to generate a description" + } + ], + "id": "humanInputAgentflow_0-input-humanInputDescriptionType-options", + "display": true + }, + { + "label": "Description", + "name": "humanInputDescription", + "type": "string", + "placeholder": "Are you sure you want to proceed?", + "acceptVariable": true, + "rows": 4, + "show": { + "humanInputDescriptionType": "fixed" + }, + "id": "humanInputAgentflow_0-input-humanInputDescription-string", + "display": true + }, { "label": "Model", - "name": "agentModel", + "name": "humanInputModel", "type": "asyncOptions", "loadMethod": "listModels", "loadConfig": true, - "id": "agentAgentflow_1-input-agentModel-asyncOptions", + "show": { + "humanInputDescriptionType": "dynamic" + }, + "id": "humanInputAgentflow_0-input-humanInputModel-asyncOptions", + "display": false + }, + { + "label": "Prompt", + "name": "humanInputModelPrompt", + "type": "string", + "default": "

Summarize the conversation between the user and the assistant, reiterate the last message from the assistant, and ask if user would like to proceed or if they have any feedback.

\n
    \n
  • Begin by capturing the key points of the conversation, ensuring that you reflect the main ideas and themes discussed.
  • \n
  • Then, clearly reproduce the last message sent by the assistant to maintain continuity. Make sure the whole message is reproduced.
  • \n
  • Finally, ask the user if they would like to proceed, or provide any feedback on the last assistant message
  • \n
\n

Output Format The output should be structured in three parts in text:

\n
    \n
  • A summary of the conversation (1-3 sentences).
  • \n
  • The last assistant message (exactly as it appeared).
  • \n
  • Ask the user if they would like to proceed, or provide any feedback on last assistant message. No other explanation and elaboration is needed.
  • \n
\n", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4, + "show": { + "humanInputDescriptionType": "dynamic" + }, + "id": "humanInputAgentflow_0-input-humanInputModelPrompt-string", + "display": false + }, + { + "label": "Enable Feedback", + "name": "humanInputEnableFeedback", + "type": "boolean", + "default": true, + "id": "humanInputAgentflow_0-input-humanInputEnableFeedback-boolean", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "humanInputDescriptionType": "fixed", + "humanInputEnableFeedback": true, + "humanInputModelConfig": { + "cache": "", + "modelName": "gpt-4o-mini", + "temperature": 0.9, + "streaming": true, + "maxTokens": "", + "topP": "", + "frequencyPenalty": "", + "presencePenalty": "", + "timeout": "", + "strictToolCalling": "", + "stopSequence": "", + "basepath": "", + "proxyUrl": "", + "baseOptions": "", + "allowImageUploads": "", + "imageResolution": "low", + "reasoningEffort": "medium", + "humanInputModel": "chatOpenAI" + }, + "humanInputDescription": "

Are you sure you want to proceed?

" + }, + "outputAnchors": [ + { + "id": "humanInputAgentflow_0-output-0", + "label": "Human Input", + "name": "humanInputAgentflow" + }, + { + "id": "humanInputAgentflow_0-output-1", + "label": "Human Input", + "name": "humanInputAgentflow" + } + ], + "outputs": { + "humanInputAgentflow": "" + }, + "selected": false + }, + "type": "agentFlow", + "width": 167, + "height": 80, + "selected": false, + "positionAbsolute": { + "x": 156.05666363734434, + "y": 86.62266545493773 + }, + "dragging": false + }, + { + "id": "loopAgentflow_0", + "position": { + "x": 392.1370040831033, + "y": 150.41190827718114 + }, + "data": { + "id": "loopAgentflow_0", + "label": "Loop back to Agent", + "version": 1, + "name": "loopAgentflow", + "type": "Loop", + "color": "#FFA07A", + "hideOutput": true, + "baseClasses": ["Loop"], + "category": "Agent Flows", + "description": "Loop back to a previous node", + "inputParams": [ + { + "label": "Loop Back To", + "name": "loopBackToNode", + "type": "asyncOptions", + "loadMethod": "listPreviousNodes", + "freeSolo": true, + "id": "loopAgentflow_0-input-loopBackToNode-asyncOptions", + "display": true + }, + { + "label": "Max Loop Count", + "name": "maxLoopCount", + "type": "number", + "default": 5, + "id": "loopAgentflow_0-input-maxLoopCount-number", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "loopBackToNode": "agentAgentflow_0-Email Reply Agent", + "maxLoopCount": 5 + }, + "outputAnchors": [], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 198, + "height": 66, + "selected": false, + "positionAbsolute": { + "x": 392.1370040831033, + "y": 150.41190827718114 + }, + "dragging": false + }, + { + "id": "toolAgentflow_0", + "position": { + "x": 607.0106274902857, + "y": 44.74028001269521 + }, + "data": { + "id": "toolAgentflow_0", + "label": "Send Email", + "version": 1.1, + "name": "toolAgentflow", + "type": "Tool", + "color": "#d4a373", + "baseClasses": ["Tool"], + "category": "Agent Flows", + "description": "Tools allow LLM to interact with external systems", + "inputParams": [ + { + "label": "Tool", + "name": "toolAgentflowSelectedTool", + "type": "asyncOptions", + "loadMethod": "listTools", + "loadConfig": true, + "id": "toolAgentflow_0-input-toolAgentflowSelectedTool-asyncOptions", + "display": true + }, + { + "label": "Tool Input Arguments", + "name": "toolInputArgs", + "type": "array", + "acceptVariable": true, + "refresh": true, + "array": [ + { + "label": "Input Argument Name", + "name": "inputArgName", + "type": "asyncOptions", + "loadMethod": "listToolInputArgs", + "refresh": true + }, + { + "label": "Input Argument Value", + "name": "inputArgValue", + "type": "string", + "acceptVariable": true + } + ], + "show": { + "toolAgentflowSelectedTool": ".+" + }, + "id": "toolAgentflow_0-input-toolInputArgs-array", + "display": true + }, + { + "label": "Update Flow State", + "name": "toolUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "toolAgentflow_0-input-toolUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "toolAgentflowSelectedTool": "gmail", + "toolInputArgs": [ + { + "inputArgName": "to", + "inputArgValue": "

{{ $form.from }}

" + }, + { + "inputArgName": "subject", + "inputArgValue": "

{{ llmAgentflow_0.output.subject }}

" + }, + { + "inputArgName": "body", + "inputArgValue": "

{{ llmAgentflow_0.output.body }}

" + } + ], + "toolUpdateState": "", + "toolAgentflowSelectedToolConfig": { + "gmailType": "messages", + "messageActions": "[\"sendMessage\"]", + "toolAgentflowSelectedTool": "gmail" + }, + "undefined": "" + }, + "outputAnchors": [ + { + "id": "toolAgentflow_0-output-toolAgentflow", + "label": "Tool", + "name": "toolAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 143, + "height": 68, + "selected": false, + "positionAbsolute": { + "x": 607.0106274902857, + "y": 44.74028001269521 + }, + "dragging": false + }, + { + "id": "llmAgentflow_0", + "position": { + "x": 368.9022119252032, + "y": 43.50583396320786 + }, + "data": { + "id": "llmAgentflow_0", + "label": "Email Subject & Body", + "version": 1, + "name": "llmAgentflow", + "type": "LLM", + "color": "#64B5F6", + "baseClasses": ["LLM"], + "category": "Agent Flows", + "description": "Large language models to analyze user-provided inputs and generate responses", + "inputParams": [ + { + "label": "Model", + "name": "llmModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "llmAgentflow_0-input-llmModel-asyncOptions", "display": true }, { "label": "Messages", - "name": "agentMessages", + "name": "llmMessages", "type": "array", "optional": true, "acceptVariable": true, @@ -1026,120 +960,22 @@ "rows": 4 } ], - "id": "agentAgentflow_1-input-agentMessages-array", - "display": true - }, - { - "label": "Tools", - "name": "agentTools", - "type": "array", - "optional": true, - "array": [ - { - "label": "Tool", - "name": "agentSelectedTool", - "type": "asyncOptions", - "loadMethod": "listTools", - "loadConfig": true - }, - { - "label": "Require Human Input", - "name": "agentSelectedToolRequiresHumanInput", - "type": "boolean", - "optional": true - } - ], - "id": "agentAgentflow_1-input-agentTools-array", - "display": true - }, - { - "label": "Knowledge (Document Stores)", - "name": "agentKnowledgeDocumentStores", - "type": "array", - "description": "Give your agent context about different document sources. Document stores must be upserted in advance.", - "array": [ - { - "label": "Document Store", - "name": "documentStore", - "type": "asyncOptions", - "loadMethod": "listStores" - }, - { - "label": "Describe Knowledge", - "name": "docStoreDescription", - "type": "string", - "generateDocStoreDescription": true, - "placeholder": "Describe what the knowledge base is about, this is useful for the AI to know when and how to search for correct information", - "rows": 4 - }, - { - "label": "Return Source Documents", - "name": "returnSourceDocuments", - "type": "boolean", - "optional": true - } - ], - "optional": true, - "id": "agentAgentflow_1-input-agentKnowledgeDocumentStores-array", - "display": true - }, - { - "label": "Knowledge (Vector Embeddings)", - "name": "agentKnowledgeVSEmbeddings", - "type": "array", - "description": "Give your agent context about different document sources from existing vector stores and embeddings", - "array": [ - { - "label": "Vector Store", - "name": "vectorStore", - "type": "asyncOptions", - "loadMethod": "listVectorStores", - "loadConfig": true - }, - { - "label": "Embedding Model", - "name": "embeddingModel", - "type": "asyncOptions", - "loadMethod": "listEmbeddings", - "loadConfig": true - }, - { - "label": "Knowledge Name", - "name": "knowledgeName", - "type": "string", - "placeholder": "A short name for the knowledge base, this is useful for the AI to know when and how to search for correct information" - }, - { - "label": "Describe Knowledge", - "name": "knowledgeDescription", - "type": "string", - "placeholder": "Describe what the knowledge base is about, this is useful for the AI to know when and how to search for correct information", - "rows": 4 - }, - { - "label": "Return Source Documents", - "name": "returnSourceDocuments", - "type": "boolean", - "optional": true - } - ], - "optional": true, - "id": "agentAgentflow_1-input-agentKnowledgeVSEmbeddings-array", + "id": "llmAgentflow_0-input-llmMessages-array", "display": true }, { "label": "Enable Memory", - "name": "agentEnableMemory", + "name": "llmEnableMemory", "type": "boolean", "description": "Enable memory for the conversation thread", "default": true, "optional": true, - "id": "agentAgentflow_1-input-agentEnableMemory-boolean", + "id": "llmAgentflow_0-input-llmEnableMemory-boolean", "display": true }, { "label": "Memory Type", - "name": "agentMemoryType", + "name": "llmMemoryType", "type": "options", "options": [ { @@ -1166,52 +1002,52 @@ "optional": true, "default": "allMessages", "show": { - "agentEnableMemory": true + "llmEnableMemory": true }, - "id": "agentAgentflow_1-input-agentMemoryType-options", + "id": "llmAgentflow_0-input-llmMemoryType-options", "display": true }, { "label": "Window Size", - "name": "agentMemoryWindowSize", + "name": "llmMemoryWindowSize", "type": "number", "default": "20", "description": "Uses a fixed window size to surface the last N messages", "show": { - "agentMemoryType": "windowSize" + "llmMemoryType": "windowSize" }, - "id": "agentAgentflow_1-input-agentMemoryWindowSize-number", + "id": "llmAgentflow_0-input-llmMemoryWindowSize-number", "display": false }, { "label": "Max Token Limit", - "name": "agentMemoryMaxTokenLimit", + "name": "llmMemoryMaxTokenLimit", "type": "number", "default": "2000", "description": "Summarize conversations once token limit is reached. Default to 2000", "show": { - "agentMemoryType": "conversationSummaryBuffer" + "llmMemoryType": "conversationSummaryBuffer" }, - "id": "agentAgentflow_1-input-agentMemoryMaxTokenLimit-number", + "id": "llmAgentflow_0-input-llmMemoryMaxTokenLimit-number", "display": false }, { "label": "Input Message", - "name": "agentUserMessage", + "name": "llmUserMessage", "type": "string", "description": "Add an input message as user message at the end of the conversation", "rows": 4, "optional": true, "acceptVariable": true, "show": { - "agentEnableMemory": true + "llmEnableMemory": true }, - "id": "agentAgentflow_1-input-agentUserMessage-string", + "id": "llmAgentflow_0-input-llmUserMessage-string", "display": true }, { "label": "Return Response As", - "name": "agentReturnResponseAs", + "name": "llmReturnResponseAs", "type": "options", "options": [ { @@ -1224,12 +1060,88 @@ } ], "default": "userMessage", - "id": "agentAgentflow_1-input-agentReturnResponseAs-options", + "id": "llmAgentflow_0-input-llmReturnResponseAs-options", + "display": true + }, + { + "label": "JSON Structured Output", + "name": "llmStructuredOutput", + "description": "Instruct the LLM to give output in a JSON structured schema", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string" + }, + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "String Array", + "name": "stringArray" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Enum", + "name": "enum" + }, + { + "label": "JSON Array", + "name": "jsonArray" + } + ] + }, + { + "label": "Enum Values", + "name": "enumValues", + "type": "string", + "placeholder": "value1, value2, value3", + "description": "Enum values. Separated by comma", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "enum" + } + }, + { + "label": "JSON Schema", + "name": "jsonSchema", + "type": "code", + "placeholder": "{\n \"answer\": {\n \"type\": \"string\",\n \"description\": \"Value of the answer\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"description\": \"Reason for the answer\"\n },\n \"optional\": {\n \"type\": \"boolean\"\n },\n \"count\": {\n \"type\": \"number\"\n },\n \"children\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\",\n \"description\": \"Value of the children's answer\"\n }\n }\n }\n }\n}", + "description": "JSON schema for the structured output", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "jsonArray" + } + }, + { + "label": "Description", + "name": "description", + "type": "string", + "placeholder": "Description of the key" + } + ], + "id": "llmAgentflow_0-input-llmStructuredOutput-array", "display": true }, { "label": "Update Flow State", - "name": "agentUpdateState", + "name": "llmUpdateState", "description": "Update runtime state during the execution of the workflow", "type": "array", "optional": true, @@ -1250,27 +1162,36 @@ "acceptNodeOutputAsVariable": true } ], - "id": "agentAgentflow_1-input-agentUpdateState-array", + "id": "llmAgentflow_0-input-llmUpdateState-array", "display": true } ], "inputAnchors": [], "inputs": { - "agentModel": "chatOpenAI", - "agentMessages": [ + "llmModel": "chatOpenAI", + "llmMessages": [], + "llmEnableMemory": true, + "llmMemoryType": "allMessages", + "llmUserMessage": "", + "llmReturnResponseAs": "userMessage", + "llmStructuredOutput": [ { - "role": "system", - "content": "

You are a senior financial analyst. You will be provided with the original query and a set of raw search summaries. Your task is to synthesize these into a long‑form markdown report (at least several paragraphs) including a short executive summary and follow‑up questions

" + "key": "subject", + "type": "string", + "enumValues": "", + "jsonSchema": "", + "description": "Subject of the email" + }, + { + "key": "body", + "type": "string", + "enumValues": "", + "jsonSchema": "", + "description": "Body of the email" } ], - "agentTools": "", - "agentKnowledgeDocumentStores": "", - "agentEnableMemory": true, - "agentMemoryType": "allMessages", - "agentUserMessage": "

Original query: {{ $form.query }}

Summarized search results: {{ iterationAgentflow_0 }}

", - "agentReturnResponseAs": "userMessage", - "agentUpdateState": "", - "agentModelConfig": { + "llmUpdateState": "", + "llmModelConfig": { "cache": "", "modelName": "gpt-4o-mini", "temperature": 0.9, @@ -1288,182 +1209,26 @@ "allowImageUploads": "", "imageResolution": "low", "reasoningEffort": "medium", - "agentModel": "chatOpenAI" + "llmModel": "chatOpenAI" } }, "outputAnchors": [ { - "id": "agentAgentflow_1-output-agentAgentflow", - "label": "Agent", - "name": "agentAgentflow" + "id": "llmAgentflow_0-output-llmAgentflow", + "label": "LLM", + "name": "llmAgentflow" } ], "outputs": {}, "selected": false }, "type": "agentFlow", - "width": 168, - "height": 71, + "width": 209, + "height": 72, "selected": false, "positionAbsolute": { - "x": 461.76351005035474, - "y": 81.71183989476083 - }, - "dragging": false - }, - { - "id": "stickyNoteAgentflow_0", - "position": { - "x": 214.77714507955716, - "y": -165.2444952661696 - }, - "data": { - "id": "stickyNoteAgentflow_0", - "label": "Sticky Note", - "version": 1, - "name": "stickyNoteAgentflow", - "type": "StickyNote", - "color": "#fee440", - "baseClasses": ["StickyNote"], - "category": "Agent Flows", - "description": "Add notes to the agent flow", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNoteAgentflow_0-input-note-string", - "display": true - } - ], - "inputAnchors": [], - "inputs": { - "note": "Search Agent will iterate through the search terms and search the web using tool" - }, - "outputAnchors": [ - { - "id": "stickyNoteAgentflow_0-output-stickyNoteAgentflow", - "label": "Sticky Note", - "name": "stickyNoteAgentflow" - } - ], - "outputs": {}, - "selected": false - }, - "type": "stickyNote", - "width": 189, - "height": 142, - "selected": false, - "positionAbsolute": { - "x": 214.77714507955716, - "y": -165.2444952661696 - }, - "dragging": false - }, - { - "id": "stickyNoteAgentflow_1", - "position": { - "x": -100.05436009717414, - "y": -45.56902388417101 - }, - "data": { - "id": "stickyNoteAgentflow_1", - "label": "Sticky Note (1)", - "version": 1, - "name": "stickyNoteAgentflow", - "type": "StickyNote", - "color": "#fee440", - "baseClasses": ["StickyNote"], - "category": "Agent Flows", - "description": "Add notes to the agent flow", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNoteAgentflow_1-input-note-string", - "display": true - } - ], - "inputAnchors": [], - "inputs": { - "note": "Planner will generate list of search terms to query for" - }, - "outputAnchors": [ - { - "id": "stickyNoteAgentflow_1-output-stickyNoteAgentflow", - "label": "Sticky Note", - "name": "stickyNoteAgentflow" - } - ], - "outputs": {}, - "selected": false - }, - "type": "stickyNote", - "width": 189, - "height": 101, - "selected": false, - "positionAbsolute": { - "x": -100.05436009717414, - "y": -45.56902388417101 - }, - "dragging": false - }, - { - "id": "stickyNoteAgentflow_2", - "position": { - "x": 457.98399139175314, - "y": -35.19227767879839 - }, - "data": { - "id": "stickyNoteAgentflow_2", - "label": "Sticky Note (2)", - "version": 1, - "name": "stickyNoteAgentflow", - "type": "StickyNote", - "color": "#fee440", - "baseClasses": ["StickyNote"], - "category": "Agent Flows", - "description": "Add notes to the agent flow", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNoteAgentflow_2-input-note-string", - "display": true - } - ], - "inputAnchors": [], - "inputs": { - "note": "Generate the final report from the search results" - }, - "outputAnchors": [ - { - "id": "stickyNoteAgentflow_2-output-stickyNoteAgentflow", - "label": "Sticky Note", - "name": "stickyNoteAgentflow" - } - ], - "outputs": {}, - "selected": false - }, - "type": "stickyNote", - "width": 189, - "height": 101, - "selected": false, - "positionAbsolute": { - "x": 457.98399139175314, - "y": -35.19227767879839 + "x": 368.9022119252032, + "y": 43.50583396320786 }, "dragging": false } @@ -1472,41 +1237,69 @@ { "source": "startAgentflow_0", "sourceHandle": "startAgentflow_0-output-startAgentflow", - "target": "llmAgentflow_0", - "targetHandle": "llmAgentflow_0", + "target": "agentAgentflow_0", + "targetHandle": "agentAgentflow_0", "data": { "sourceColor": "#7EE787", - "targetColor": "#64B5F6", - "isHumanInput": false - }, - "type": "agentFlow", - "id": "startAgentflow_0-startAgentflow_0-output-startAgentflow-llmAgentflow_0-llmAgentflow_0" - }, - { - "source": "llmAgentflow_0", - "sourceHandle": "llmAgentflow_0-output-llmAgentflow", - "target": "iterationAgentflow_0", - "targetHandle": "iterationAgentflow_0", - "data": { - "sourceColor": "#64B5F6", - "targetColor": "#9C89B8", - "isHumanInput": false - }, - "type": "agentFlow", - "id": "llmAgentflow_0-llmAgentflow_0-output-llmAgentflow-iterationAgentflow_0-iterationAgentflow_0" - }, - { - "source": "iterationAgentflow_0", - "sourceHandle": "iterationAgentflow_0-output-iterationAgentflow", - "target": "agentAgentflow_1", - "targetHandle": "agentAgentflow_1", - "data": { - "sourceColor": "#9C89B8", "targetColor": "#4DD0E1", "isHumanInput": false }, "type": "agentFlow", - "id": "iterationAgentflow_0-iterationAgentflow_0-output-iterationAgentflow-agentAgentflow_1-agentAgentflow_1" + "id": "startAgentflow_0-startAgentflow_0-output-startAgentflow-agentAgentflow_0-agentAgentflow_0" + }, + { + "source": "agentAgentflow_0", + "sourceHandle": "agentAgentflow_0-output-agentAgentflow", + "target": "humanInputAgentflow_0", + "targetHandle": "humanInputAgentflow_0", + "data": { + "sourceColor": "#4DD0E1", + "targetColor": "#6E6EFD", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "agentAgentflow_0-agentAgentflow_0-output-agentAgentflow-humanInputAgentflow_0-humanInputAgentflow_0" + }, + { + "source": "humanInputAgentflow_0", + "sourceHandle": "humanInputAgentflow_0-output-1", + "target": "loopAgentflow_0", + "targetHandle": "loopAgentflow_0", + "data": { + "sourceColor": "#6E6EFD", + "targetColor": "#FFA07A", + "edgeLabel": "reject", + "isHumanInput": true + }, + "type": "agentFlow", + "id": "humanInputAgentflow_0-humanInputAgentflow_0-output-1-loopAgentflow_0-loopAgentflow_0" + }, + { + "source": "humanInputAgentflow_0", + "sourceHandle": "humanInputAgentflow_0-output-0", + "target": "llmAgentflow_0", + "targetHandle": "llmAgentflow_0", + "data": { + "sourceColor": "#6E6EFD", + "targetColor": "#64B5F6", + "edgeLabel": "proceed", + "isHumanInput": true + }, + "type": "agentFlow", + "id": "humanInputAgentflow_0-humanInputAgentflow_0-output-0-llmAgentflow_0-llmAgentflow_0" + }, + { + "source": "llmAgentflow_0", + "sourceHandle": "llmAgentflow_0-output-llmAgentflow", + "target": "toolAgentflow_0", + "targetHandle": "toolAgentflow_0", + "data": { + "sourceColor": "#64B5F6", + "targetColor": "#d4a373", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "llmAgentflow_0-llmAgentflow_0-output-llmAgentflow-toolAgentflow_0-toolAgentflow_0" } ] } diff --git a/packages/server/marketplaces/agentflowsv2/Interacting With API.json b/packages/server/marketplaces/agentflowsv2/Interacting With API.json new file mode 100644 index 00000000..5638a8c0 --- /dev/null +++ b/packages/server/marketplaces/agentflowsv2/Interacting With API.json @@ -0,0 +1,1294 @@ +{ + "description": "Different ways of agents that can interact with APIs", + "usecases": ["Interacting with API"], + "nodes": [ + { + "id": "startAgentflow_0", + "type": "agentFlow", + "position": { + "x": 122, + "y": 46.5 + }, + "data": { + "id": "startAgentflow_0", + "label": "Start", + "version": 1.1, + "name": "startAgentflow", + "type": "Start", + "color": "#7EE787", + "hideInput": true, + "baseClasses": ["Start"], + "category": "Agent Flows", + "description": "Starting point of the agentflow", + "inputParams": [ + { + "label": "Input Type", + "name": "startInputType", + "type": "options", + "options": [ + { + "label": "Chat Input", + "name": "chatInput", + "description": "Start the conversation with chat input" + }, + { + "label": "Form Input", + "name": "formInput", + "description": "Start the workflow with form inputs" + } + ], + "default": "chatInput", + "id": "startAgentflow_0-input-startInputType-options", + "display": true + }, + { + "label": "Form Title", + "name": "formTitle", + "type": "string", + "placeholder": "Please Fill Out The Form", + "show": { + "startInputType": "formInput" + }, + "id": "startAgentflow_0-input-formTitle-string", + "display": false + }, + { + "label": "Form Description", + "name": "formDescription", + "type": "string", + "placeholder": "Complete all fields below to continue", + "show": { + "startInputType": "formInput" + }, + "id": "startAgentflow_0-input-formDescription-string", + "display": false + }, + { + "label": "Form Input Types", + "name": "formInputTypes", + "description": "Specify the type of form input", + "type": "array", + "show": { + "startInputType": "formInput" + }, + "array": [ + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Options", + "name": "options" + } + ], + "default": "string" + }, + { + "label": "Label", + "name": "label", + "type": "string", + "placeholder": "Label for the input" + }, + { + "label": "Variable Name", + "name": "name", + "type": "string", + "placeholder": "Variable name for the input (must be camel case)", + "description": "Variable name must be camel case. For example: firstName, lastName, etc." + }, + { + "label": "Add Options", + "name": "addOptions", + "type": "array", + "show": { + "formInputTypes[$index].type": "options" + }, + "array": [ + { + "label": "Option", + "name": "option", + "type": "string" + } + ] + } + ], + "id": "startAgentflow_0-input-formInputTypes-array", + "display": false + }, + { + "label": "Ephemeral Memory", + "name": "startEphemeralMemory", + "type": "boolean", + "description": "Start fresh for every execution without past chat history", + "optional": true, + "id": "startAgentflow_0-input-startEphemeralMemory-boolean", + "display": true + }, + { + "label": "Flow State", + "name": "startState", + "description": "Runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string", + "placeholder": "Foo" + }, + { + "label": "Value", + "name": "value", + "type": "string", + "placeholder": "Bar", + "optional": true + } + ], + "id": "startAgentflow_0-input-startState-array", + "display": true + }, + { + "label": "Persist State", + "name": "startPersistState", + "type": "boolean", + "description": "Persist the state in the same session", + "optional": true, + "id": "startAgentflow_0-input-startPersistState-boolean", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "startInputType": "chatInput", + "formTitle": "", + "formDescription": "", + "formInputTypes": "", + "startEphemeralMemory": "", + "startState": "", + "startPersistState": "" + }, + "outputAnchors": [ + { + "id": "startAgentflow_0-output-startAgentflow", + "label": "Start", + "name": "startAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "width": 103, + "height": 66, + "positionAbsolute": { + "x": 122, + "y": 46.5 + }, + "selected": false, + "dragging": false + }, + { + "id": "agentAgentflow_0", + "position": { + "x": 276.5, + "y": 30 + }, + "data": { + "id": "agentAgentflow_0", + "label": "Requests Agent", + "version": 1, + "name": "agentAgentflow", + "type": "Agent", + "color": "#4DD0E1", + "baseClasses": ["Agent"], + "category": "Agent Flows", + "description": "Dynamically choose and utilize tools during runtime, enabling multi-step reasoning", + "inputParams": [ + { + "label": "Model", + "name": "agentModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "agentAgentflow_0-input-agentModel-asyncOptions", + "display": true + }, + { + "label": "Messages", + "name": "agentMessages", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Role", + "name": "role", + "type": "options", + "options": [ + { + "label": "System", + "name": "system" + }, + { + "label": "Assistant", + "name": "assistant" + }, + { + "label": "Developer", + "name": "developer" + }, + { + "label": "User", + "name": "user" + } + ] + }, + { + "label": "Content", + "name": "content", + "type": "string", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4 + } + ], + "id": "agentAgentflow_0-input-agentMessages-array", + "display": true + }, + { + "label": "Tools", + "name": "agentTools", + "type": "array", + "optional": true, + "array": [ + { + "label": "Tool", + "name": "agentSelectedTool", + "type": "asyncOptions", + "loadMethod": "listTools", + "loadConfig": true + }, + { + "label": "Require Human Input", + "name": "agentSelectedToolRequiresHumanInput", + "type": "boolean", + "optional": true + } + ], + "id": "agentAgentflow_0-input-agentTools-array", + "display": true + }, + { + "label": "Knowledge (Document Stores)", + "name": "agentKnowledgeDocumentStores", + "type": "array", + "description": "Give your agent context about different document sources. Document stores must be upserted in advance.", + "array": [ + { + "label": "Document Store", + "name": "documentStore", + "type": "asyncOptions", + "loadMethod": "listStores" + }, + { + "label": "Describe Knowledge", + "name": "docStoreDescription", + "type": "string", + "generateDocStoreDescription": true, + "placeholder": "Describe what the knowledge base is about, this is useful for the AI to know when and how to search for correct information", + "rows": 4 + }, + { + "label": "Return Source Documents", + "name": "returnSourceDocuments", + "type": "boolean", + "optional": true + } + ], + "optional": true, + "id": "agentAgentflow_0-input-agentKnowledgeDocumentStores-array", + "display": true + }, + { + "label": "Knowledge (Vector Embeddings)", + "name": "agentKnowledgeVSEmbeddings", + "type": "array", + "description": "Give your agent context about different document sources from existing vector stores and embeddings", + "array": [ + { + "label": "Vector Store", + "name": "vectorStore", + "type": "asyncOptions", + "loadMethod": "listVectorStores", + "loadConfig": true + }, + { + "label": "Embedding Model", + "name": "embeddingModel", + "type": "asyncOptions", + "loadMethod": "listEmbeddings", + "loadConfig": true + }, + { + "label": "Knowledge Name", + "name": "knowledgeName", + "type": "string", + "placeholder": "A short name for the knowledge base, this is useful for the AI to know when and how to search for correct information" + }, + { + "label": "Describe Knowledge", + "name": "knowledgeDescription", + "type": "string", + "placeholder": "Describe what the knowledge base is about, this is useful for the AI to know when and how to search for correct information", + "rows": 4 + }, + { + "label": "Return Source Documents", + "name": "returnSourceDocuments", + "type": "boolean", + "optional": true + } + ], + "optional": true, + "id": "agentAgentflow_0-input-agentKnowledgeVSEmbeddings-array", + "display": true + }, + { + "label": "Enable Memory", + "name": "agentEnableMemory", + "type": "boolean", + "description": "Enable memory for the conversation thread", + "default": true, + "optional": true, + "id": "agentAgentflow_0-input-agentEnableMemory-boolean", + "display": true + }, + { + "label": "Memory Type", + "name": "agentMemoryType", + "type": "options", + "options": [ + { + "label": "All Messages", + "name": "allMessages", + "description": "Retrieve all messages from the conversation" + }, + { + "label": "Window Size", + "name": "windowSize", + "description": "Uses a fixed window size to surface the last N messages" + }, + { + "label": "Conversation Summary", + "name": "conversationSummary", + "description": "Summarizes the whole conversation" + }, + { + "label": "Conversation Summary Buffer", + "name": "conversationSummaryBuffer", + "description": "Summarize conversations once token limit is reached. Default to 2000" + } + ], + "optional": true, + "default": "allMessages", + "show": { + "agentEnableMemory": true + }, + "id": "agentAgentflow_0-input-agentMemoryType-options", + "display": true + }, + { + "label": "Window Size", + "name": "agentMemoryWindowSize", + "type": "number", + "default": "20", + "description": "Uses a fixed window size to surface the last N messages", + "show": { + "agentMemoryType": "windowSize" + }, + "id": "agentAgentflow_0-input-agentMemoryWindowSize-number", + "display": false + }, + { + "label": "Max Token Limit", + "name": "agentMemoryMaxTokenLimit", + "type": "number", + "default": "2000", + "description": "Summarize conversations once token limit is reached. Default to 2000", + "show": { + "agentMemoryType": "conversationSummaryBuffer" + }, + "id": "agentAgentflow_0-input-agentMemoryMaxTokenLimit-number", + "display": false + }, + { + "label": "Input Message", + "name": "agentUserMessage", + "type": "string", + "description": "Add an input message as user message at the end of the conversation", + "rows": 4, + "optional": true, + "acceptVariable": true, + "show": { + "agentEnableMemory": true + }, + "id": "agentAgentflow_0-input-agentUserMessage-string", + "display": true + }, + { + "label": "Return Response As", + "name": "agentReturnResponseAs", + "type": "options", + "options": [ + { + "label": "User Message", + "name": "userMessage" + }, + { + "label": "Assistant Message", + "name": "assistantMessage" + } + ], + "default": "userMessage", + "id": "agentAgentflow_0-input-agentReturnResponseAs-options", + "display": true + }, + { + "label": "Update Flow State", + "name": "agentUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "agentAgentflow_0-input-agentUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "agentModel": "chatOpenAI", + "agentMessages": [ + { + "role": "system", + "content": "

You are helpful assistant.

Todays date time is {{ current_date_time }}

" + } + ], + "agentTools": [ + { + "agentSelectedTool": "requestsGet", + "agentSelectedToolRequiresHumanInput": "", + "agentSelectedToolConfig": { + "requestsGetUrl": "

http://localhost:5566/events

", + "requestsGetName": "get_events", + "requestsGetDescription": "Use this when you need to get events", + "requestsGetHeaders": "", + "requestsGetQueryParamsSchema": "{\n \"id\": {\n \"type\": \"string\",\n \"in\": \"path\",\n \"description\": \"ID of the item to get. /:id\"\n },\n \"limit\": {\n \"type\": \"string\",\n \"in\": \"query\",\n \"description\": \"Limit the number of items to get. ?limit=10\"\n }\n}", + "requestsGetMaxOutputLength": "2000", + "agentSelectedTool": "requestsGet" + } + }, + { + "agentSelectedTool": "requestsPost", + "agentSelectedToolRequiresHumanInput": "", + "agentSelectedToolConfig": { + "requestsPostUrl": "

http://localhost:5566/events

", + "requestsPostName": "create_event", + "requestsPostDescription": "Use this when you want to create a new event", + "requestsPostHeaders": "", + "requestPostBody": "", + "requestsPostBodySchema": "{\n \"name\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"Name of the event\"\n },\n \"date\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"Date of the event\"\n },\n \"location\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"Location of the event\"\n }\n}", + "requestsPostMaxOutputLength": "2000", + "agentSelectedTool": "requestsPost" + } + }, + { + "agentSelectedTool": "requestsPut", + "agentSelectedToolRequiresHumanInput": "", + "agentSelectedToolConfig": { + "requestsPutUrl": "

http://localhost:5566/events

", + "requestsPutName": "update_event", + "requestsPutDescription": "Use this when you want to update an event", + "requestsPutHeaders": "", + "requestPutBody": "", + "requestsPutBodySchema": "{\n \"name\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"Name of the event\"\n },\n \"date\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"Date of the event\"\n },\n \"location\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"Location of the event\"\n }\n}", + "requestsPutMaxOutputLength": "2000", + "agentSelectedTool": "requestsPut" + } + }, + { + "agentSelectedTool": "requestsDelete", + "agentSelectedToolRequiresHumanInput": "", + "agentSelectedToolConfig": { + "requestsDeleteUrl": "

http://localhost:5566/events

", + "requestsDeleteName": "delete_event", + "requestsDeleteDescription": "Use this when you need to delete event", + "requestsDeleteHeaders": "", + "requestsDeleteQueryParamsSchema": "{\n \"id\": {\n \"type\": \"string\",\n \"required\": true,\n \"in\": \"path\",\n \"description\": \"ID of the item to delete. /:id\"\n }\n}", + "requestsDeleteMaxOutputLength": "2000", + "agentSelectedTool": "requestsDelete" + } + } + ], + "agentKnowledgeDocumentStores": [], + "agentKnowledgeVSEmbeddings": "", + "agentEnableMemory": true, + "agentMemoryType": "allMessages", + "agentUserMessage": "", + "agentReturnResponseAs": "userMessage", + "agentUpdateState": "", + "agentModelConfig": { + "credential": "", + "modelName": "gpt-4o-mini", + "temperature": 0.9, + "streaming": true, + "maxTokens": "", + "topP": "", + "frequencyPenalty": "", + "presencePenalty": "", + "timeout": "", + "strictToolCalling": "", + "stopSequence": "", + "basepath": "", + "proxyUrl": "", + "baseOptions": "", + "allowImageUploads": "", + "imageResolution": "low", + "reasoningEffort": "medium", + "agentModel": "chatOpenAI" + } + }, + "outputAnchors": [ + { + "id": "agentAgentflow_0-output-agentAgentflow", + "label": "Agent", + "name": "agentAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 176, + "height": 100, + "selected": false, + "positionAbsolute": { + "x": 276.5, + "y": 30 + }, + "dragging": false + }, + { + "id": "agentAgentflow_1", + "position": { + "x": 486.5, + "y": 30.25 + }, + "data": { + "id": "agentAgentflow_1", + "label": "OpenAPI Agent", + "version": 1, + "name": "agentAgentflow", + "type": "Agent", + "color": "#4DD0E1", + "baseClasses": ["Agent"], + "category": "Agent Flows", + "description": "Dynamically choose and utilize tools during runtime, enabling multi-step reasoning", + "inputParams": [ + { + "label": "Model", + "name": "agentModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "agentAgentflow_1-input-agentModel-asyncOptions", + "display": true + }, + { + "label": "Messages", + "name": "agentMessages", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Role", + "name": "role", + "type": "options", + "options": [ + { + "label": "System", + "name": "system" + }, + { + "label": "Assistant", + "name": "assistant" + }, + { + "label": "Developer", + "name": "developer" + }, + { + "label": "User", + "name": "user" + } + ] + }, + { + "label": "Content", + "name": "content", + "type": "string", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4 + } + ], + "id": "agentAgentflow_1-input-agentMessages-array", + "display": true + }, + { + "label": "Tools", + "name": "agentTools", + "type": "array", + "optional": true, + "array": [ + { + "label": "Tool", + "name": "agentSelectedTool", + "type": "asyncOptions", + "loadMethod": "listTools", + "loadConfig": true + }, + { + "label": "Require Human Input", + "name": "agentSelectedToolRequiresHumanInput", + "type": "boolean", + "optional": true + } + ], + "id": "agentAgentflow_1-input-agentTools-array", + "display": true + }, + { + "label": "Knowledge (Document Stores)", + "name": "agentKnowledgeDocumentStores", + "type": "array", + "description": "Give your agent context about different document sources. Document stores must be upserted in advance.", + "array": [ + { + "label": "Document Store", + "name": "documentStore", + "type": "asyncOptions", + "loadMethod": "listStores" + }, + { + "label": "Describe Knowledge", + "name": "docStoreDescription", + "type": "string", + "generateDocStoreDescription": true, + "placeholder": "Describe what the knowledge base is about, this is useful for the AI to know when and how to search for correct information", + "rows": 4 + }, + { + "label": "Return Source Documents", + "name": "returnSourceDocuments", + "type": "boolean", + "optional": true + } + ], + "optional": true, + "id": "agentAgentflow_1-input-agentKnowledgeDocumentStores-array", + "display": true + }, + { + "label": "Knowledge (Vector Embeddings)", + "name": "agentKnowledgeVSEmbeddings", + "type": "array", + "description": "Give your agent context about different document sources from existing vector stores and embeddings", + "array": [ + { + "label": "Vector Store", + "name": "vectorStore", + "type": "asyncOptions", + "loadMethod": "listVectorStores", + "loadConfig": true + }, + { + "label": "Embedding Model", + "name": "embeddingModel", + "type": "asyncOptions", + "loadMethod": "listEmbeddings", + "loadConfig": true + }, + { + "label": "Knowledge Name", + "name": "knowledgeName", + "type": "string", + "placeholder": "A short name for the knowledge base, this is useful for the AI to know when and how to search for correct information" + }, + { + "label": "Describe Knowledge", + "name": "knowledgeDescription", + "type": "string", + "placeholder": "Describe what the knowledge base is about, this is useful for the AI to know when and how to search for correct information", + "rows": 4 + }, + { + "label": "Return Source Documents", + "name": "returnSourceDocuments", + "type": "boolean", + "optional": true + } + ], + "optional": true, + "id": "agentAgentflow_1-input-agentKnowledgeVSEmbeddings-array", + "display": true + }, + { + "label": "Enable Memory", + "name": "agentEnableMemory", + "type": "boolean", + "description": "Enable memory for the conversation thread", + "default": true, + "optional": true, + "id": "agentAgentflow_1-input-agentEnableMemory-boolean", + "display": true + }, + { + "label": "Memory Type", + "name": "agentMemoryType", + "type": "options", + "options": [ + { + "label": "All Messages", + "name": "allMessages", + "description": "Retrieve all messages from the conversation" + }, + { + "label": "Window Size", + "name": "windowSize", + "description": "Uses a fixed window size to surface the last N messages" + }, + { + "label": "Conversation Summary", + "name": "conversationSummary", + "description": "Summarizes the whole conversation" + }, + { + "label": "Conversation Summary Buffer", + "name": "conversationSummaryBuffer", + "description": "Summarize conversations once token limit is reached. Default to 2000" + } + ], + "optional": true, + "default": "allMessages", + "show": { + "agentEnableMemory": true + }, + "id": "agentAgentflow_1-input-agentMemoryType-options", + "display": true + }, + { + "label": "Window Size", + "name": "agentMemoryWindowSize", + "type": "number", + "default": "20", + "description": "Uses a fixed window size to surface the last N messages", + "show": { + "agentMemoryType": "windowSize" + }, + "id": "agentAgentflow_1-input-agentMemoryWindowSize-number", + "display": false + }, + { + "label": "Max Token Limit", + "name": "agentMemoryMaxTokenLimit", + "type": "number", + "default": "2000", + "description": "Summarize conversations once token limit is reached. Default to 2000", + "show": { + "agentMemoryType": "conversationSummaryBuffer" + }, + "id": "agentAgentflow_1-input-agentMemoryMaxTokenLimit-number", + "display": false + }, + { + "label": "Input Message", + "name": "agentUserMessage", + "type": "string", + "description": "Add an input message as user message at the end of the conversation", + "rows": 4, + "optional": true, + "acceptVariable": true, + "show": { + "agentEnableMemory": true + }, + "id": "agentAgentflow_1-input-agentUserMessage-string", + "display": true + }, + { + "label": "Return Response As", + "name": "agentReturnResponseAs", + "type": "options", + "options": [ + { + "label": "User Message", + "name": "userMessage" + }, + { + "label": "Assistant Message", + "name": "assistantMessage" + } + ], + "default": "userMessage", + "id": "agentAgentflow_1-input-agentReturnResponseAs-options", + "display": true + }, + { + "label": "Update Flow State", + "name": "agentUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "agentAgentflow_1-input-agentUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "agentModel": "chatAnthropic", + "agentMessages": [ + { + "role": "system", + "content": "

You are helpful assistant.

Todays date time is {{ current_date_time }}

" + } + ], + "agentTools": [ + { + "agentSelectedTool": "openAPIToolkit", + "agentSelectedToolRequiresHumanInput": "", + "agentSelectedToolConfig": { + "yamlFile": "", + "returnDirect": "", + "headers": "", + "removeNulls": "", + "customCode": "const fetch = require('node-fetch');\nconst url = $url;\nconst options = $options;\n\ntry {\n\tconst response = await fetch(url, options);\n\tconst resp = await response.json();\n\treturn JSON.stringify(resp);\n} catch (error) {\n\tconsole.error(error);\n\treturn '';\n}\n", + "agentSelectedTool": "openAPIToolkit" + } + } + ], + "agentKnowledgeDocumentStores": "", + "agentKnowledgeVSEmbeddings": "", + "agentEnableMemory": true, + "agentMemoryType": "allMessages", + "agentUserMessage": "", + "agentReturnResponseAs": "userMessage", + "agentUpdateState": "", + "agentModelConfig": { + "cache": "", + "modelName": "claude-sonnet-4-0", + "temperature": 0.9, + "streaming": true, + "maxTokensToSample": "", + "topP": "", + "topK": "", + "extendedThinking": "", + "budgetTokens": 1024, + "allowImageUploads": "", + "agentModel": "chatAnthropic" + } + }, + "outputAnchors": [ + { + "id": "agentAgentflow_1-output-agentAgentflow", + "label": "Agent", + "name": "agentAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 213, + "height": 100, + "selected": false, + "positionAbsolute": { + "x": 486.5, + "y": 30.25 + }, + "dragging": false + }, + { + "id": "stickyNoteAgentflow_0", + "position": { + "x": 359.646787967208, + "y": -168.84288303219904 + }, + "data": { + "id": "stickyNoteAgentflow_0", + "label": "Sticky Note", + "version": 1, + "name": "stickyNoteAgentflow", + "type": "StickyNote", + "color": "#fee440", + "baseClasses": ["StickyNote"], + "category": "Agent Flows", + "description": "Add notes to the agent flow", + "inputParams": [ + { + "label": "", + "name": "note", + "type": "string", + "rows": 1, + "placeholder": "Type something here", + "optional": true, + "id": "stickyNoteAgentflow_0-input-note-string", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "note": "There are two ways of interacting with API\n\n- Request GET, PUT, POST, DELETE tools\n\n- OpenAPI Toolkit" + }, + "outputAnchors": [ + { + "id": "stickyNoteAgentflow_0-output-stickyNoteAgentflow", + "label": "Sticky Note", + "name": "stickyNoteAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "stickyNote", + "width": 210, + "height": 183, + "selected": false, + "positionAbsolute": { + "x": 359.646787967208, + "y": -168.84288303219904 + }, + "dragging": false + }, + { + "id": "httpAgentflow_0", + "position": { + "x": 738.2972542041965, + "y": 46.68491774985176 + }, + "data": { + "id": "httpAgentflow_0", + "label": "Send HTTP Request", + "version": 1.1, + "name": "httpAgentflow", + "type": "HTTP", + "color": "#FF7F7F", + "baseClasses": ["HTTP"], + "category": "Agent Flows", + "description": "Send a HTTP request", + "inputParams": [ + { + "label": "HTTP Credential", + "name": "credential", + "type": "credential", + "credentialNames": ["httpBasicAuth", "httpBearerToken", "httpApiKey"], + "optional": true, + "id": "httpAgentflow_0-input-credential-credential", + "display": true + }, + { + "label": "Method", + "name": "method", + "type": "options", + "options": [ + { + "label": "GET", + "name": "GET" + }, + { + "label": "POST", + "name": "POST" + }, + { + "label": "PUT", + "name": "PUT" + }, + { + "label": "DELETE", + "name": "DELETE" + }, + { + "label": "PATCH", + "name": "PATCH" + } + ], + "default": "GET", + "id": "httpAgentflow_0-input-method-options", + "display": true + }, + { + "label": "URL", + "name": "url", + "type": "string", + "id": "httpAgentflow_0-input-url-string", + "display": true + }, + { + "label": "Headers", + "name": "headers", + "type": "array", + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string", + "default": "" + }, + { + "label": "Value", + "name": "value", + "type": "string", + "default": "", + "acceptVariable": true + } + ], + "optional": true, + "id": "httpAgentflow_0-input-headers-array", + "display": true + }, + { + "label": "Query Params", + "name": "queryParams", + "type": "array", + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string", + "default": "" + }, + { + "label": "Value", + "name": "value", + "type": "string", + "default": "", + "acceptVariable": true + } + ], + "optional": true, + "id": "httpAgentflow_0-input-queryParams-array", + "display": true + }, + { + "label": "Body Type", + "name": "bodyType", + "type": "options", + "options": [ + { + "label": "JSON", + "name": "json" + }, + { + "label": "Raw", + "name": "raw" + }, + { + "label": "Form Data", + "name": "formData" + }, + { + "label": "x-www-form-urlencoded", + "name": "xWwwFormUrlencoded" + } + ], + "optional": true, + "id": "httpAgentflow_0-input-bodyType-options", + "display": true + }, + { + "label": "Body", + "name": "body", + "type": "string", + "acceptVariable": true, + "rows": 4, + "show": { + "bodyType": ["raw", "json"] + }, + "optional": true, + "id": "httpAgentflow_0-input-body-string", + "display": false + }, + { + "label": "Body", + "name": "body", + "type": "array", + "acceptVariable": true, + "show": { + "bodyType": ["xWwwFormUrlencoded", "formData"] + }, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string", + "default": "" + }, + { + "label": "Value", + "name": "value", + "type": "string", + "default": "", + "acceptVariable": true + } + ], + "optional": true, + "id": "httpAgentflow_0-input-body-array", + "display": false + }, + { + "label": "Response Type", + "name": "responseType", + "type": "options", + "options": [ + { + "label": "JSON", + "name": "json" + }, + { + "label": "Text", + "name": "text" + }, + { + "label": "Array Buffer", + "name": "arraybuffer" + }, + { + "label": "Raw (Base64)", + "name": "base64" + } + ], + "optional": true, + "id": "httpAgentflow_0-input-responseType-options", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "method": "GET", + "url": "", + "headers": "", + "queryParams": "", + "bodyType": "", + "body": "", + "responseType": "" + }, + "outputAnchors": [ + { + "id": "httpAgentflow_0-output-httpAgentflow", + "label": "HTTP", + "name": "httpAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 202, + "height": 66, + "selected": false, + "positionAbsolute": { + "x": 738.2972542041965, + "y": 46.68491774985176 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "startAgentflow_0", + "sourceHandle": "startAgentflow_0-output-startAgentflow", + "target": "agentAgentflow_0", + "targetHandle": "agentAgentflow_0", + "data": { + "sourceColor": "#7EE787", + "targetColor": "#4DD0E1", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "startAgentflow_0-startAgentflow_0-output-startAgentflow-agentAgentflow_0-agentAgentflow_0" + }, + { + "source": "agentAgentflow_0", + "sourceHandle": "agentAgentflow_0-output-agentAgentflow", + "target": "agentAgentflow_1", + "targetHandle": "agentAgentflow_1", + "data": { + "sourceColor": "#4DD0E1", + "targetColor": "#4DD0E1", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "agentAgentflow_0-agentAgentflow_0-output-agentAgentflow-agentAgentflow_1-agentAgentflow_1" + }, + { + "source": "agentAgentflow_1", + "sourceHandle": "agentAgentflow_1-output-agentAgentflow", + "target": "httpAgentflow_0", + "targetHandle": "httpAgentflow_0", + "data": { + "sourceColor": "#4DD0E1", + "targetColor": "#FF7F7F", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "agentAgentflow_1-agentAgentflow_1-output-agentAgentflow-httpAgentflow_0-httpAgentflow_0" + } + ] +} diff --git a/packages/server/marketplaces/agentflowsv2/SQL Agent.json b/packages/server/marketplaces/agentflowsv2/SQL Agent.json new file mode 100644 index 00000000..4c86fede --- /dev/null +++ b/packages/server/marketplaces/agentflowsv2/SQL Agent.json @@ -0,0 +1,2052 @@ +{ + "description": "An agent that can perform question answering over a database", + "usecases": ["SQL"], + "nodes": [ + { + "id": "startAgentflow_0", + "type": "agentFlow", + "position": { + "x": -97, + "y": 108 + }, + "data": { + "id": "startAgentflow_0", + "label": "Start", + "version": 1.1, + "name": "startAgentflow", + "type": "Start", + "color": "#7EE787", + "hideInput": true, + "baseClasses": ["Start"], + "category": "Agent Flows", + "description": "Starting point of the agentflow", + "inputParams": [ + { + "label": "Input Type", + "name": "startInputType", + "type": "options", + "options": [ + { + "label": "Chat Input", + "name": "chatInput", + "description": "Start the conversation with chat input" + }, + { + "label": "Form Input", + "name": "formInput", + "description": "Start the workflow with form inputs" + } + ], + "default": "chatInput", + "id": "startAgentflow_0-input-startInputType-options", + "display": true + }, + { + "label": "Form Title", + "name": "formTitle", + "type": "string", + "placeholder": "Please Fill Out The Form", + "show": { + "startInputType": "formInput" + }, + "id": "startAgentflow_0-input-formTitle-string", + "display": false + }, + { + "label": "Form Description", + "name": "formDescription", + "type": "string", + "placeholder": "Complete all fields below to continue", + "show": { + "startInputType": "formInput" + }, + "id": "startAgentflow_0-input-formDescription-string", + "display": false + }, + { + "label": "Form Input Types", + "name": "formInputTypes", + "description": "Specify the type of form input", + "type": "array", + "show": { + "startInputType": "formInput" + }, + "array": [ + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Options", + "name": "options" + } + ], + "default": "string" + }, + { + "label": "Label", + "name": "label", + "type": "string", + "placeholder": "Label for the input" + }, + { + "label": "Variable Name", + "name": "name", + "type": "string", + "placeholder": "Variable name for the input (must be camel case)", + "description": "Variable name must be camel case. For example: firstName, lastName, etc." + }, + { + "label": "Add Options", + "name": "addOptions", + "type": "array", + "show": { + "formInputTypes[$index].type": "options" + }, + "array": [ + { + "label": "Option", + "name": "option", + "type": "string" + } + ] + } + ], + "id": "startAgentflow_0-input-formInputTypes-array", + "display": false + }, + { + "label": "Ephemeral Memory", + "name": "startEphemeralMemory", + "type": "boolean", + "description": "Start fresh for every execution without past chat history", + "optional": true, + "id": "startAgentflow_0-input-startEphemeralMemory-boolean", + "display": true + }, + { + "label": "Flow State", + "name": "startState", + "description": "Runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string", + "placeholder": "Foo" + }, + { + "label": "Value", + "name": "value", + "type": "string", + "placeholder": "Bar", + "optional": true + } + ], + "id": "startAgentflow_0-input-startState-array", + "display": true + }, + { + "label": "Persist State", + "name": "startPersistState", + "type": "boolean", + "description": "Persist the state in the same session", + "optional": true, + "id": "startAgentflow_0-input-startPersistState-boolean", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "startInputType": "chatInput", + "formTitle": "", + "formDescription": "", + "formInputTypes": "", + "startEphemeralMemory": "", + "startState": [ + { + "key": "sqlQuery", + "value": "" + } + ], + "startPersistState": "" + }, + "outputAnchors": [ + { + "id": "startAgentflow_0-output-startAgentflow", + "label": "Start", + "name": "startAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "width": 103, + "height": 66, + "selected": false, + "positionAbsolute": { + "x": -97, + "y": 108 + }, + "dragging": false + }, + { + "id": "customFunctionAgentflow_0", + "position": { + "x": 58.5, + "y": 109 + }, + "data": { + "id": "customFunctionAgentflow_0", + "label": "Get DB Schema", + "version": 1, + "name": "customFunctionAgentflow", + "type": "CustomFunction", + "color": "#E4B7FF", + "baseClasses": ["CustomFunction"], + "category": "Agent Flows", + "description": "Execute custom function", + "inputParams": [ + { + "label": "Input Variables", + "name": "customFunctionInputVariables", + "description": "Input variables can be used in the function with prefix $. For example: $foo", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Variable Name", + "name": "variableName", + "type": "string" + }, + { + "label": "Variable Value", + "name": "variableValue", + "type": "string", + "acceptVariable": true + } + ], + "id": "customFunctionAgentflow_0-input-customFunctionInputVariables-array", + "display": true + }, + { + "label": "Javascript Function", + "name": "customFunctionJavascriptFunction", + "type": "code", + "codeExample": "/*\n* You can use any libraries imported in Flowise\n* You can use properties specified in Input Schema as variables. Ex: Property = userid, Variable = $userid\n* You can get default flow config: $flow.sessionId, $flow.chatId, $flow.chatflowId, $flow.input, $flow.state\n* You can get custom variables: $vars.\n* Must return a string value at the end of function\n*/\n\nconst fetch = require('node-fetch');\nconst url = 'https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true';\nconst options = {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n }\n};\ntry {\n const response = await fetch(url, options);\n const text = await response.text();\n return text;\n} catch (error) {\n console.error(error);\n return '';\n}", + "description": "The function to execute. Must return a string or an object that can be converted to a string.", + "id": "customFunctionAgentflow_0-input-customFunctionJavascriptFunction-code", + "display": true + }, + { + "label": "Update Flow State", + "name": "customFunctionUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "customFunctionAgentflow_0-input-customFunctionUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "customFunctionInputVariables": "", + "customFunctionJavascriptFunction": "const { DataSource } = require('typeorm');\n\nconst HOST = 'localhost';\nconst USER = 'testuser';\nconst PASSWORD = 'testpwd';\nconst DATABASE = 'abudhabi';\nconst PORT = 5555;\n\nlet sqlSchemaPrompt = '';\n\nconst AppDataSource = new DataSource({\n type: 'postgres',\n host: HOST,\n port: PORT,\n username: USER,\n password: PASSWORD,\n database: DATABASE,\n synchronize: false,\n logging: false,\n});\n\nasync function getSQLPrompt() {\n try {\n await AppDataSource.initialize();\n const queryRunner = AppDataSource.createQueryRunner();\n\n // Get all user-defined tables (excluding system tables)\n const tablesResult = await queryRunner.query(`\n SELECT table_name\n FROM information_schema.tables\n WHERE table_schema = 'public' AND table_type = 'BASE TABLE'\n `);\n\n for (const tableRow of tablesResult) {\n const tableName = tableRow.table_name;\n\n const schemaInfo = await queryRunner.query(`\n SELECT column_name, data_type, is_nullable\n FROM information_schema.columns\n WHERE table_name = '${tableName}'\n `);\n\n const createColumns = [];\n const columnNames = [];\n\n for (const column of schemaInfo) {\n const name = column.column_name;\n const type = column.data_type.toUpperCase();\n const notNull = column.is_nullable === 'NO' ? 'NOT NULL' : '';\n columnNames.push(name);\n createColumns.push(`${name} ${type} ${notNull}`);\n }\n\n const sqlCreateTableQuery = `CREATE TABLE ${tableName} (${createColumns.join(', ')})`;\n const sqlSelectTableQuery = `SELECT * FROM ${tableName} LIMIT 3`;\n\n let allValues = [];\n try {\n const rows = await queryRunner.query(sqlSelectTableQuery);\n\n allValues = rows.map(row =>\n columnNames.map(col => row[col]).join(' ')\n );\n } catch (err) {\n allValues.push('[ERROR FETCHING ROWS]');\n }\n\n sqlSchemaPrompt +=\n sqlCreateTableQuery +\n '\\n' +\n sqlSelectTableQuery +\n '\\n' +\n columnNames.join(' ') +\n '\\n' +\n allValues.join('\\n') +\n '\\n\\n';\n }\n\n await queryRunner.release();\n } catch (err) {\n console.error(err);\n throw err;\n }\n}\n\nasync function main() {\n await getSQLPrompt();\n}\n\nawait main();\n\nreturn sqlSchemaPrompt;\n", + "customFunctionUpdateState": "" + }, + "outputAnchors": [ + { + "id": "customFunctionAgentflow_0-output-customFunctionAgentflow", + "label": "Custom Function", + "name": "customFunctionAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 173, + "height": 66, + "selected": false, + "positionAbsolute": { + "x": 58.5, + "y": 109 + }, + "dragging": false + }, + { + "id": "llmAgentflow_0", + "position": { + "x": 272.7184381707814, + "y": 106.61165168988839 + }, + "data": { + "id": "llmAgentflow_0", + "label": "Generate SQL Query", + "version": 1, + "name": "llmAgentflow", + "type": "LLM", + "color": "#64B5F6", + "baseClasses": ["LLM"], + "category": "Agent Flows", + "description": "Large language models to analyze user-provided inputs and generate responses", + "inputParams": [ + { + "label": "Model", + "name": "llmModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "llmAgentflow_0-input-llmModel-asyncOptions", + "display": true + }, + { + "label": "Messages", + "name": "llmMessages", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Role", + "name": "role", + "type": "options", + "options": [ + { + "label": "System", + "name": "system" + }, + { + "label": "Assistant", + "name": "assistant" + }, + { + "label": "Developer", + "name": "developer" + }, + { + "label": "User", + "name": "user" + } + ] + }, + { + "label": "Content", + "name": "content", + "type": "string", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4 + } + ], + "id": "llmAgentflow_0-input-llmMessages-array", + "display": true + }, + { + "label": "Enable Memory", + "name": "llmEnableMemory", + "type": "boolean", + "description": "Enable memory for the conversation thread", + "default": true, + "optional": true, + "id": "llmAgentflow_0-input-llmEnableMemory-boolean", + "display": true + }, + { + "label": "Memory Type", + "name": "llmMemoryType", + "type": "options", + "options": [ + { + "label": "All Messages", + "name": "allMessages", + "description": "Retrieve all messages from the conversation" + }, + { + "label": "Window Size", + "name": "windowSize", + "description": "Uses a fixed window size to surface the last N messages" + }, + { + "label": "Conversation Summary", + "name": "conversationSummary", + "description": "Summarizes the whole conversation" + }, + { + "label": "Conversation Summary Buffer", + "name": "conversationSummaryBuffer", + "description": "Summarize conversations once token limit is reached. Default to 2000" + } + ], + "optional": true, + "default": "allMessages", + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_0-input-llmMemoryType-options", + "display": true + }, + { + "label": "Window Size", + "name": "llmMemoryWindowSize", + "type": "number", + "default": "20", + "description": "Uses a fixed window size to surface the last N messages", + "show": { + "llmMemoryType": "windowSize" + }, + "id": "llmAgentflow_0-input-llmMemoryWindowSize-number", + "display": false + }, + { + "label": "Max Token Limit", + "name": "llmMemoryMaxTokenLimit", + "type": "number", + "default": "2000", + "description": "Summarize conversations once token limit is reached. Default to 2000", + "show": { + "llmMemoryType": "conversationSummaryBuffer" + }, + "id": "llmAgentflow_0-input-llmMemoryMaxTokenLimit-number", + "display": false + }, + { + "label": "Input Message", + "name": "llmUserMessage", + "type": "string", + "description": "Add an input message as user message at the end of the conversation", + "rows": 4, + "optional": true, + "acceptVariable": true, + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_0-input-llmUserMessage-string", + "display": true + }, + { + "label": "Return Response As", + "name": "llmReturnResponseAs", + "type": "options", + "options": [ + { + "label": "User Message", + "name": "userMessage" + }, + { + "label": "Assistant Message", + "name": "assistantMessage" + } + ], + "default": "userMessage", + "id": "llmAgentflow_0-input-llmReturnResponseAs-options", + "display": true + }, + { + "label": "JSON Structured Output", + "name": "llmStructuredOutput", + "description": "Instruct the LLM to give output in a JSON structured schema", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string" + }, + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "String Array", + "name": "stringArray" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Enum", + "name": "enum" + }, + { + "label": "JSON Array", + "name": "jsonArray" + } + ] + }, + { + "label": "Enum Values", + "name": "enumValues", + "type": "string", + "placeholder": "value1, value2, value3", + "description": "Enum values. Separated by comma", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "enum" + } + }, + { + "label": "JSON Schema", + "name": "jsonSchema", + "type": "code", + "placeholder": "{\n \"answer\": {\n \"type\": \"string\",\n \"description\": \"Value of the answer\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"description\": \"Reason for the answer\"\n },\n \"optional\": {\n \"type\": \"boolean\"\n },\n \"count\": {\n \"type\": \"number\"\n },\n \"children\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\",\n \"description\": \"Value of the children's answer\"\n }\n }\n }\n }\n}", + "description": "JSON schema for the structured output", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "jsonArray" + } + }, + { + "label": "Description", + "name": "description", + "type": "string", + "placeholder": "Description of the key" + } + ], + "id": "llmAgentflow_0-input-llmStructuredOutput-array", + "display": true + }, + { + "label": "Update Flow State", + "name": "llmUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "llmAgentflow_0-input-llmUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "llmModel": "chatAnthropic", + "llmMessages": [ + { + "role": "system", + "content": "

You are an agent designed to interact with a SQL database. Given an input question, create a syntactically correct sqlite query to run, then look at the results of the query and return the answer. Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most 5 results. You can order the results by a relevant column to return the most interesting examples in the database. Never query for all the columns from a specific table, only ask for the relevant columns given the question. DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.

Here is the relevant table info:

{{ customFunctionAgentflow_0 }}

Note:

  • Only generate ONE SQL query

" + } + ], + "llmEnableMemory": true, + "llmMemoryType": "allMessages", + "llmUserMessage": "", + "llmReturnResponseAs": "userMessage", + "llmStructuredOutput": [ + { + "key": "sql_query", + "type": "string", + "enumValues": "", + "jsonSchema": "", + "description": "SQL query" + } + ], + "llmUpdateState": [ + { + "key": "sqlQuery", + "value": "

{{ output.sql_query }}

" + } + ], + "llmModelConfig": { + "credential": "", + "modelName": "claude-sonnet-4-0", + "temperature": 0.9, + "streaming": true, + "maxTokensToSample": "", + "topP": "", + "topK": "", + "extendedThinking": "", + "budgetTokens": 1024, + "allowImageUploads": "", + "llmModel": "chatAnthropic" + } + }, + "outputAnchors": [ + { + "id": "llmAgentflow_0-output-llmAgentflow", + "label": "LLM", + "name": "llmAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 213, + "height": 72, + "selected": false, + "positionAbsolute": { + "x": 272.7184381707814, + "y": 106.61165168988839 + }, + "dragging": false + }, + { + "id": "conditionAgentAgentflow_0", + "position": { + "x": 511.16504493033483, + "y": 101.98220225318451 + }, + "data": { + "id": "conditionAgentAgentflow_0", + "label": "Check SQL Query", + "version": 1, + "name": "conditionAgentAgentflow", + "type": "ConditionAgent", + "color": "#ff8fab", + "baseClasses": ["ConditionAgent"], + "category": "Agent Flows", + "description": "Utilize an agent to split flows based on dynamic conditions", + "inputParams": [ + { + "label": "Model", + "name": "conditionAgentModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "conditionAgentAgentflow_0-input-conditionAgentModel-asyncOptions", + "display": true + }, + { + "label": "Instructions", + "name": "conditionAgentInstructions", + "type": "string", + "description": "A general instructions of what the condition agent should do", + "rows": 4, + "acceptVariable": true, + "placeholder": "Determine if the user is interested in learning about AI", + "id": "conditionAgentAgentflow_0-input-conditionAgentInstructions-string", + "display": true + }, + { + "label": "Input", + "name": "conditionAgentInput", + "type": "string", + "description": "Input to be used for the condition agent", + "rows": 4, + "acceptVariable": true, + "default": "

{{ question }}

", + "id": "conditionAgentAgentflow_0-input-conditionAgentInput-string", + "display": true + }, + { + "label": "Scenarios", + "name": "conditionAgentScenarios", + "description": "Define the scenarios that will be used as the conditions to split the flow", + "type": "array", + "array": [ + { + "label": "Scenario", + "name": "scenario", + "type": "string", + "placeholder": "User is asking for a pizza" + } + ], + "default": [ + { + "scenario": "SQL query is correct and does not contains mistakes" + }, + { + "scenario": "SQL query contains mistakes" + } + ], + "id": "conditionAgentAgentflow_0-input-conditionAgentScenarios-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "conditionAgentModel": "chatOpenAI", + "conditionAgentInstructions": "

You are a SQL expert with a strong attention to detail. Double check the SQL query for common mistakes, including:

- Using NOT IN with NULL values

- Using UNION when UNION ALL should have been used

- Using BETWEEN for exclusive ranges

- Data type mismatch in predicates

- Properly quoting identifiers

- Using the correct number of arguments for functions

- Casting to the correct data type

- Using the proper columns for joins

", + "conditionAgentInput": "

{{ $flow.state.sqlQuery }}

", + "conditionAgentScenarios": [ + { + "scenario": "SQL query is correct and does not contains mistakes" + }, + { + "scenario": "SQL query contains mistakes" + } + ], + "conditionAgentModelConfig": { + "credential": "", + "modelName": "gpt-4o-mini", + "temperature": 0.9, + "streaming": true, + "maxTokens": "", + "topP": "", + "frequencyPenalty": "", + "presencePenalty": "", + "timeout": "", + "strictToolCalling": "", + "stopSequence": "", + "basepath": "", + "proxyUrl": "", + "baseOptions": "", + "allowImageUploads": "", + "imageResolution": "low", + "reasoningEffort": "medium", + "conditionAgentModel": "chatOpenAI" + } + }, + "outputAnchors": [ + { + "id": "conditionAgentAgentflow_0-output-0", + "label": "Condition Agent", + "name": "conditionAgentAgentflow" + }, + { + "id": "conditionAgentAgentflow_0-output-1", + "label": "Condition Agent", + "name": "conditionAgentAgentflow" + } + ], + "outputs": { + "conditionAgentAgentflow": "" + }, + "selected": false + }, + "type": "agentFlow", + "width": 187, + "height": 80, + "selected": false, + "positionAbsolute": { + "x": 511.16504493033483, + "y": 101.98220225318451 + }, + "dragging": false + }, + { + "id": "loopAgentflow_0", + "position": { + "x": 762.44734302386, + "y": 182.95996068910745 + }, + "data": { + "id": "loopAgentflow_0", + "label": "Regenerate Query", + "version": 1, + "name": "loopAgentflow", + "type": "Loop", + "color": "#FFA07A", + "hideOutput": true, + "baseClasses": ["Loop"], + "category": "Agent Flows", + "description": "Loop back to a previous node", + "inputParams": [ + { + "label": "Loop Back To", + "name": "loopBackToNode", + "type": "asyncOptions", + "loadMethod": "listPreviousNodes", + "freeSolo": true, + "id": "loopAgentflow_0-input-loopBackToNode-asyncOptions", + "display": true + }, + { + "label": "Max Loop Count", + "name": "maxLoopCount", + "type": "number", + "default": 5, + "id": "loopAgentflow_0-input-maxLoopCount-number", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "loopBackToNode": "llmAgentflow_0-Generate SQL Query", + "maxLoopCount": 5 + }, + "outputAnchors": [], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 190, + "height": 66, + "selected": false, + "positionAbsolute": { + "x": 762.44734302386, + "y": 182.95996068910745 + }, + "dragging": false + }, + { + "id": "customFunctionAgentflow_1", + "position": { + "x": 761.3261621815544, + "y": 44.65096212173265 + }, + "data": { + "id": "customFunctionAgentflow_1", + "label": "Run SQL Query", + "version": 1, + "name": "customFunctionAgentflow", + "type": "CustomFunction", + "color": "#E4B7FF", + "baseClasses": ["CustomFunction"], + "category": "Agent Flows", + "description": "Execute custom function", + "inputParams": [ + { + "label": "Input Variables", + "name": "customFunctionInputVariables", + "description": "Input variables can be used in the function with prefix $. For example: $foo", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Variable Name", + "name": "variableName", + "type": "string" + }, + { + "label": "Variable Value", + "name": "variableValue", + "type": "string", + "acceptVariable": true + } + ], + "id": "customFunctionAgentflow_1-input-customFunctionInputVariables-array", + "display": true + }, + { + "label": "Javascript Function", + "name": "customFunctionJavascriptFunction", + "type": "code", + "codeExample": "/*\n* You can use any libraries imported in Flowise\n* You can use properties specified in Input Schema as variables. Ex: Property = userid, Variable = $userid\n* You can get default flow config: $flow.sessionId, $flow.chatId, $flow.chatflowId, $flow.input, $flow.state\n* You can get custom variables: $vars.\n* Must return a string value at the end of function\n*/\n\nconst fetch = require('node-fetch');\nconst url = 'https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true';\nconst options = {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json'\n }\n};\ntry {\n const response = await fetch(url, options);\n const text = await response.text();\n return text;\n} catch (error) {\n console.error(error);\n return '';\n}", + "description": "The function to execute. Must return a string or an object that can be converted to a string.", + "id": "customFunctionAgentflow_1-input-customFunctionJavascriptFunction-code", + "display": true + }, + { + "label": "Update Flow State", + "name": "customFunctionUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "customFunctionAgentflow_1-input-customFunctionUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "customFunctionInputVariables": [ + { + "variableName": "sqlQuery", + "variableValue": "

{{ $flow.state.sqlQuery }}

" + } + ], + "customFunctionJavascriptFunction": "const { DataSource } = require('typeorm');\n\n// Configuration\nconst HOST = 'localhost';\nconst USER = 'testuser';\nconst PASSWORD = 'testpwd';\nconst DATABASE = 'abudhabi';\nconst PORT = 5555;\n\nconst sqlQuery = $sqlQuery;\n\nconst AppDataSource = new DataSource({\n type: 'postgres',\n host: HOST,\n port: PORT,\n username: USER,\n password: PASSWORD,\n database: DATABASE,\n synchronize: false,\n logging: false,\n});\n\nlet formattedResult = '';\n\nasync function runSQLQuery(query) {\n try {\n await AppDataSource.initialize();\n const queryRunner = AppDataSource.createQueryRunner();\n\n const rows = await queryRunner.query(query);\n console.log('rows =', rows);\n\n if (rows.length === 0) {\n formattedResult = '[No results returned]';\n } else {\n const columnNames = Object.keys(rows[0]);\n const header = columnNames.join(' ');\n const values = rows.map(row =>\n columnNames.map(col => row[col]).join(' ')\n );\n\n formattedResult = query + '\\n' + header + '\\n' + values.join('\\n');\n }\n\n await queryRunner.release();\n } catch (err) {\n console.error('[ERROR]', err);\n formattedResult = `[Error executing query]: ${err}`;\n }\n\n return formattedResult;\n}\n\nasync function main() {\n formattedResult = await runSQLQuery(sqlQuery);\n}\n\nawait main();\n\nreturn formattedResult;\n", + "customFunctionUpdateState": "" + }, + "outputAnchors": [ + { + "id": "customFunctionAgentflow_1-output-customFunctionAgentflow", + "label": "Custom Function", + "name": "customFunctionAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 171, + "height": 66, + "selected": false, + "positionAbsolute": { + "x": 761.3261621815544, + "y": 44.65096212173265 + }, + "dragging": false + }, + { + "id": "llmAgentflow_1", + "position": { + "x": 1238.7660285501179, + "y": 20.56658816269558 + }, + "data": { + "id": "llmAgentflow_1", + "label": "Return Response", + "version": 1, + "name": "llmAgentflow", + "type": "LLM", + "color": "#64B5F6", + "baseClasses": ["LLM"], + "category": "Agent Flows", + "description": "Large language models to analyze user-provided inputs and generate responses", + "inputParams": [ + { + "label": "Model", + "name": "llmModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "llmAgentflow_1-input-llmModel-asyncOptions", + "display": true + }, + { + "label": "Messages", + "name": "llmMessages", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Role", + "name": "role", + "type": "options", + "options": [ + { + "label": "System", + "name": "system" + }, + { + "label": "Assistant", + "name": "assistant" + }, + { + "label": "Developer", + "name": "developer" + }, + { + "label": "User", + "name": "user" + } + ] + }, + { + "label": "Content", + "name": "content", + "type": "string", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4 + } + ], + "id": "llmAgentflow_1-input-llmMessages-array", + "display": true + }, + { + "label": "Enable Memory", + "name": "llmEnableMemory", + "type": "boolean", + "description": "Enable memory for the conversation thread", + "default": true, + "optional": true, + "id": "llmAgentflow_1-input-llmEnableMemory-boolean", + "display": true + }, + { + "label": "Memory Type", + "name": "llmMemoryType", + "type": "options", + "options": [ + { + "label": "All Messages", + "name": "allMessages", + "description": "Retrieve all messages from the conversation" + }, + { + "label": "Window Size", + "name": "windowSize", + "description": "Uses a fixed window size to surface the last N messages" + }, + { + "label": "Conversation Summary", + "name": "conversationSummary", + "description": "Summarizes the whole conversation" + }, + { + "label": "Conversation Summary Buffer", + "name": "conversationSummaryBuffer", + "description": "Summarize conversations once token limit is reached. Default to 2000" + } + ], + "optional": true, + "default": "allMessages", + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_1-input-llmMemoryType-options", + "display": true + }, + { + "label": "Window Size", + "name": "llmMemoryWindowSize", + "type": "number", + "default": "20", + "description": "Uses a fixed window size to surface the last N messages", + "show": { + "llmMemoryType": "windowSize" + }, + "id": "llmAgentflow_1-input-llmMemoryWindowSize-number", + "display": false + }, + { + "label": "Max Token Limit", + "name": "llmMemoryMaxTokenLimit", + "type": "number", + "default": "2000", + "description": "Summarize conversations once token limit is reached. Default to 2000", + "show": { + "llmMemoryType": "conversationSummaryBuffer" + }, + "id": "llmAgentflow_1-input-llmMemoryMaxTokenLimit-number", + "display": false + }, + { + "label": "Input Message", + "name": "llmUserMessage", + "type": "string", + "description": "Add an input message as user message at the end of the conversation", + "rows": 4, + "optional": true, + "acceptVariable": true, + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_1-input-llmUserMessage-string", + "display": true + }, + { + "label": "Return Response As", + "name": "llmReturnResponseAs", + "type": "options", + "options": [ + { + "label": "User Message", + "name": "userMessage" + }, + { + "label": "Assistant Message", + "name": "assistantMessage" + } + ], + "default": "userMessage", + "id": "llmAgentflow_1-input-llmReturnResponseAs-options", + "display": true + }, + { + "label": "JSON Structured Output", + "name": "llmStructuredOutput", + "description": "Instruct the LLM to give output in a JSON structured schema", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string" + }, + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "String Array", + "name": "stringArray" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Enum", + "name": "enum" + }, + { + "label": "JSON Array", + "name": "jsonArray" + } + ] + }, + { + "label": "Enum Values", + "name": "enumValues", + "type": "string", + "placeholder": "value1, value2, value3", + "description": "Enum values. Separated by comma", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "enum" + } + }, + { + "label": "JSON Schema", + "name": "jsonSchema", + "type": "code", + "placeholder": "{\n \"answer\": {\n \"type\": \"string\",\n \"description\": \"Value of the answer\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"description\": \"Reason for the answer\"\n },\n \"optional\": {\n \"type\": \"boolean\"\n },\n \"count\": {\n \"type\": \"number\"\n },\n \"children\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\",\n \"description\": \"Value of the children's answer\"\n }\n }\n }\n }\n}", + "description": "JSON schema for the structured output", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "jsonArray" + } + }, + { + "label": "Description", + "name": "description", + "type": "string", + "placeholder": "Description of the key" + } + ], + "id": "llmAgentflow_1-input-llmStructuredOutput-array", + "display": true + }, + { + "label": "Update Flow State", + "name": "llmUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "llmAgentflow_1-input-llmUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "llmModel": "chatGoogleGenerativeAI", + "llmMessages": [], + "llmEnableMemory": true, + "llmMemoryType": "allMessages", + "llmUserMessage": "

{{ customFunctionAgentflow_1 }}

", + "llmReturnResponseAs": "userMessage", + "llmStructuredOutput": "", + "llmUpdateState": "", + "llmModelConfig": { + "credential": "", + "modelName": "gemini-2.0-flash", + "customModelName": "", + "temperature": 0.9, + "streaming": true, + "maxOutputTokens": "", + "topP": "", + "topK": "", + "harmCategory": "", + "harmBlockThreshold": "", + "baseUrl": "", + "allowImageUploads": "", + "llmModel": "chatGoogleGenerativeAI" + }, + "undefined": "" + }, + "outputAnchors": [ + { + "id": "llmAgentflow_1-output-llmAgentflow", + "label": "LLM", + "name": "llmAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 199, + "height": 72, + "selected": false, + "positionAbsolute": { + "x": 1238.7660285501179, + "y": 20.56658816269558 + }, + "dragging": false + }, + { + "id": "conditionAgentAgentflow_1", + "position": { + "x": 966.5436041632489, + "y": 57.77868724229256 + }, + "data": { + "id": "conditionAgentAgentflow_1", + "label": "Check Result", + "version": 1, + "name": "conditionAgentAgentflow", + "type": "ConditionAgent", + "color": "#ff8fab", + "baseClasses": ["ConditionAgent"], + "category": "Agent Flows", + "description": "Utilize an agent to split flows based on dynamic conditions", + "inputParams": [ + { + "label": "Model", + "name": "conditionAgentModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "conditionAgentAgentflow_1-input-conditionAgentModel-asyncOptions", + "display": true + }, + { + "label": "Instructions", + "name": "conditionAgentInstructions", + "type": "string", + "description": "A general instructions of what the condition agent should do", + "rows": 4, + "acceptVariable": true, + "placeholder": "Determine if the user is interested in learning about AI", + "id": "conditionAgentAgentflow_1-input-conditionAgentInstructions-string", + "display": true + }, + { + "label": "Input", + "name": "conditionAgentInput", + "type": "string", + "description": "Input to be used for the condition agent", + "rows": 4, + "acceptVariable": true, + "default": "

{{ question }}

", + "id": "conditionAgentAgentflow_1-input-conditionAgentInput-string", + "display": true + }, + { + "label": "Scenarios", + "name": "conditionAgentScenarios", + "description": "Define the scenarios that will be used as the conditions to split the flow", + "type": "array", + "array": [ + { + "label": "Scenario", + "name": "scenario", + "type": "string", + "placeholder": "User is asking for a pizza" + } + ], + "default": [ + { + "scenario": "Result is correct and does not contains error" + }, + { + "scenario": "Result query contains error" + } + ], + "id": "conditionAgentAgentflow_1-input-conditionAgentScenarios-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "conditionAgentModel": "chatMistralAI", + "conditionAgentInstructions": "

You are a SQL expert. Check if the query result is correct or contains error.

", + "conditionAgentInput": "

{{ customFunctionAgentflow_1 }}

", + "conditionAgentScenarios": [ + { + "scenario": "Result is correct and does not contains error" + }, + { + "scenario": "Result query contains error" + } + ], + "conditionAgentModelConfig": { + "credential": "", + "modelName": "mistral-medium-latest", + "temperature": 0.9, + "streaming": true, + "maxOutputTokens": "", + "topP": "", + "randomSeed": "", + "safeMode": "", + "overrideEndpoint": "", + "conditionAgentModel": "chatMistralAI" + } + }, + "outputAnchors": [ + { + "id": "conditionAgentAgentflow_1-output-0", + "label": "Condition Agent", + "name": "conditionAgentAgentflow" + }, + { + "id": "conditionAgentAgentflow_1-output-1", + "label": "Condition Agent", + "name": "conditionAgentAgentflow" + } + ], + "outputs": { + "conditionAgentAgentflow": "" + }, + "selected": false + }, + "type": "agentFlow", + "width": 228, + "height": 80, + "selected": false, + "positionAbsolute": { + "x": 966.5436041632489, + "y": 57.77868724229256 + }, + "dragging": false + }, + { + "id": "loopAgentflow_1", + "position": { + "x": 1501.0055934843515, + "y": 140.83809747682727 + }, + "data": { + "id": "loopAgentflow_1", + "label": "Recheck SQL Query", + "version": 1, + "name": "loopAgentflow", + "type": "Loop", + "color": "#FFA07A", + "hideOutput": true, + "baseClasses": ["Loop"], + "category": "Agent Flows", + "description": "Loop back to a previous node", + "inputParams": [ + { + "label": "Loop Back To", + "name": "loopBackToNode", + "type": "asyncOptions", + "loadMethod": "listPreviousNodes", + "freeSolo": true, + "id": "loopAgentflow_1-input-loopBackToNode-asyncOptions", + "display": true + }, + { + "label": "Max Loop Count", + "name": "maxLoopCount", + "type": "number", + "default": 5, + "id": "loopAgentflow_1-input-maxLoopCount-number", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "loopBackToNode": "conditionAgentAgentflow_0-Check SQL Query", + "maxLoopCount": 5, + "undefined": "" + }, + "outputAnchors": [], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 202, + "height": 66, + "selected": false, + "positionAbsolute": { + "x": 1501.0055934843515, + "y": 140.83809747682727 + }, + "dragging": false + }, + { + "id": "llmAgentflow_2", + "position": { + "x": 1235.4868883628933, + "y": 137.82100195002667 + }, + "data": { + "id": "llmAgentflow_2", + "label": "Regenerate SQL Query", + "version": 1, + "name": "llmAgentflow", + "type": "LLM", + "color": "#64B5F6", + "baseClasses": ["LLM"], + "category": "Agent Flows", + "description": "Large language models to analyze user-provided inputs and generate responses", + "inputParams": [ + { + "label": "Model", + "name": "llmModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "llmAgentflow_2-input-llmModel-asyncOptions", + "display": true + }, + { + "label": "Messages", + "name": "llmMessages", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Role", + "name": "role", + "type": "options", + "options": [ + { + "label": "System", + "name": "system" + }, + { + "label": "Assistant", + "name": "assistant" + }, + { + "label": "Developer", + "name": "developer" + }, + { + "label": "User", + "name": "user" + } + ] + }, + { + "label": "Content", + "name": "content", + "type": "string", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4 + } + ], + "id": "llmAgentflow_2-input-llmMessages-array", + "display": true + }, + { + "label": "Enable Memory", + "name": "llmEnableMemory", + "type": "boolean", + "description": "Enable memory for the conversation thread", + "default": true, + "optional": true, + "id": "llmAgentflow_2-input-llmEnableMemory-boolean", + "display": true + }, + { + "label": "Memory Type", + "name": "llmMemoryType", + "type": "options", + "options": [ + { + "label": "All Messages", + "name": "allMessages", + "description": "Retrieve all messages from the conversation" + }, + { + "label": "Window Size", + "name": "windowSize", + "description": "Uses a fixed window size to surface the last N messages" + }, + { + "label": "Conversation Summary", + "name": "conversationSummary", + "description": "Summarizes the whole conversation" + }, + { + "label": "Conversation Summary Buffer", + "name": "conversationSummaryBuffer", + "description": "Summarize conversations once token limit is reached. Default to 2000" + } + ], + "optional": true, + "default": "allMessages", + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_2-input-llmMemoryType-options", + "display": true + }, + { + "label": "Window Size", + "name": "llmMemoryWindowSize", + "type": "number", + "default": "20", + "description": "Uses a fixed window size to surface the last N messages", + "show": { + "llmMemoryType": "windowSize" + }, + "id": "llmAgentflow_2-input-llmMemoryWindowSize-number", + "display": false + }, + { + "label": "Max Token Limit", + "name": "llmMemoryMaxTokenLimit", + "type": "number", + "default": "2000", + "description": "Summarize conversations once token limit is reached. Default to 2000", + "show": { + "llmMemoryType": "conversationSummaryBuffer" + }, + "id": "llmAgentflow_2-input-llmMemoryMaxTokenLimit-number", + "display": false + }, + { + "label": "Input Message", + "name": "llmUserMessage", + "type": "string", + "description": "Add an input message as user message at the end of the conversation", + "rows": 4, + "optional": true, + "acceptVariable": true, + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_2-input-llmUserMessage-string", + "display": true + }, + { + "label": "Return Response As", + "name": "llmReturnResponseAs", + "type": "options", + "options": [ + { + "label": "User Message", + "name": "userMessage" + }, + { + "label": "Assistant Message", + "name": "assistantMessage" + } + ], + "default": "userMessage", + "id": "llmAgentflow_2-input-llmReturnResponseAs-options", + "display": true + }, + { + "label": "JSON Structured Output", + "name": "llmStructuredOutput", + "description": "Instruct the LLM to give output in a JSON structured schema", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string" + }, + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "String Array", + "name": "stringArray" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Enum", + "name": "enum" + }, + { + "label": "JSON Array", + "name": "jsonArray" + } + ] + }, + { + "label": "Enum Values", + "name": "enumValues", + "type": "string", + "placeholder": "value1, value2, value3", + "description": "Enum values. Separated by comma", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "enum" + } + }, + { + "label": "JSON Schema", + "name": "jsonSchema", + "type": "code", + "placeholder": "{\n \"answer\": {\n \"type\": \"string\",\n \"description\": \"Value of the answer\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"description\": \"Reason for the answer\"\n },\n \"optional\": {\n \"type\": \"boolean\"\n },\n \"count\": {\n \"type\": \"number\"\n },\n \"children\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\",\n \"description\": \"Value of the children's answer\"\n }\n }\n }\n }\n}", + "description": "JSON schema for the structured output", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "jsonArray" + } + }, + { + "label": "Description", + "name": "description", + "type": "string", + "placeholder": "Description of the key" + } + ], + "id": "llmAgentflow_2-input-llmStructuredOutput-array", + "display": true + }, + { + "label": "Update Flow State", + "name": "llmUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "llmAgentflow_2-input-llmUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "llmModel": "chatAnthropic", + "llmMessages": [ + { + "role": "system", + "content": "

You are an agent designed to interact with a SQL database. Given an input question, create a syntactically correct sqlite query to run, then look at the results of the query and return the answer. Unless the user specifies a specific number of examples they wish to obtain, always limit your query to at most 5 results. You can order the results by a relevant column to return the most interesting examples in the database. Never query for all the columns from a specific table, only ask for the relevant columns given the question. DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.) to the database.

Here is the relevant table info:

{{ customFunctionAgentflow_0 }}

" + } + ], + "llmEnableMemory": true, + "llmMemoryType": "allMessages", + "llmUserMessage": "

Given the generated SQL Query: {{ $flow.state.sqlQuery }}

I have the following error: {{ customFunctionAgentflow_1 }}

Regenerate a new SQL Query that will fix the error

", + "llmReturnResponseAs": "userMessage", + "llmStructuredOutput": [ + { + "key": "sql_query", + "type": "string", + "enumValues": "", + "jsonSchema": "", + "description": "SQL query" + } + ], + "llmUpdateState": [ + { + "key": "sqlQuery", + "value": "

{{ output.sql_query }}

" + } + ], + "llmModelConfig": { + "credential": "", + "modelName": "claude-sonnet-4-0", + "temperature": 0.9, + "streaming": true, + "maxTokensToSample": "", + "topP": "", + "topK": "", + "extendedThinking": "", + "budgetTokens": 1024, + "allowImageUploads": "", + "llmModel": "chatAnthropic" + } + }, + "outputAnchors": [ + { + "id": "llmAgentflow_2-output-llmAgentflow", + "label": "LLM", + "name": "llmAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 220, + "height": 72, + "selected": false, + "positionAbsolute": { + "x": 1235.4868883628933, + "y": 137.82100195002667 + }, + "dragging": false + }, + { + "id": "stickyNoteAgentflow_0", + "position": { + "x": 973.4435331695138, + "y": 156.551869199512 + }, + "data": { + "id": "stickyNoteAgentflow_0", + "label": "Sticky Note", + "version": 1, + "name": "stickyNoteAgentflow", + "type": "StickyNote", + "color": "#fee440", + "baseClasses": ["StickyNote"], + "category": "Agent Flows", + "description": "Add notes to the agent flow", + "inputParams": [ + { + "label": "", + "name": "note", + "type": "string", + "rows": 1, + "placeholder": "Type something here", + "optional": true, + "id": "stickyNoteAgentflow_0-input-note-string", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "note": "This is an auto correct mechanism that regenerate sql query if result contains error" + }, + "outputAnchors": [ + { + "id": "stickyNoteAgentflow_0-output-stickyNoteAgentflow", + "label": "Sticky Note", + "name": "stickyNoteAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "stickyNote", + "width": 210, + "height": 123, + "selected": false, + "positionAbsolute": { + "x": 973.4435331695138, + "y": 156.551869199512 + }, + "dragging": false + }, + { + "id": "stickyNoteAgentflow_1", + "position": { + "x": 514.8377809033279, + "y": 200.97994630025966 + }, + "data": { + "id": "stickyNoteAgentflow_1", + "label": "Sticky Note (1)", + "version": 1, + "name": "stickyNoteAgentflow", + "type": "StickyNote", + "color": "#fee440", + "baseClasses": ["StickyNote"], + "category": "Agent Flows", + "description": "Add notes to the agent flow", + "inputParams": [ + { + "label": "", + "name": "note", + "type": "string", + "rows": 1, + "placeholder": "Type something here", + "optional": true, + "id": "stickyNoteAgentflow_1-input-note-string", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "note": "Check if generated SQL query contains errors/mistakes, if yes - regenerate" + }, + "outputAnchors": [ + { + "id": "stickyNoteAgentflow_1-output-stickyNoteAgentflow", + "label": "Sticky Note", + "name": "stickyNoteAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "stickyNote", + "width": 210, + "height": 123, + "selected": false, + "positionAbsolute": { + "x": 514.8377809033279, + "y": 200.97994630025966 + }, + "dragging": false + }, + { + "id": "stickyNoteAgentflow_2", + "position": { + "x": 40.21835449345774, + "y": 6.978337213146034 + }, + "data": { + "id": "stickyNoteAgentflow_2", + "label": "Sticky Note (1) (2)", + "version": 1, + "name": "stickyNoteAgentflow", + "type": "StickyNote", + "color": "#fee440", + "baseClasses": ["StickyNote"], + "category": "Agent Flows", + "description": "Add notes to the agent flow", + "inputParams": [ + { + "label": "", + "name": "note", + "type": "string", + "rows": 1, + "placeholder": "Type something here", + "optional": true, + "id": "stickyNoteAgentflow_2-input-note-string", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "note": "Retrieve database schema" + }, + "outputAnchors": [ + { + "id": "stickyNoteAgentflow_2-output-stickyNoteAgentflow", + "label": "Sticky Note", + "name": "stickyNoteAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "stickyNote", + "width": 210, + "height": 82, + "selected": false, + "positionAbsolute": { + "x": 40.21835449345774, + "y": 6.978337213146034 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "startAgentflow_0", + "sourceHandle": "startAgentflow_0-output-startAgentflow", + "target": "customFunctionAgentflow_0", + "targetHandle": "customFunctionAgentflow_0", + "data": { + "sourceColor": "#7EE787", + "targetColor": "#E4B7FF", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "startAgentflow_0-startAgentflow_0-output-startAgentflow-customFunctionAgentflow_0-customFunctionAgentflow_0" + }, + { + "source": "customFunctionAgentflow_0", + "sourceHandle": "customFunctionAgentflow_0-output-customFunctionAgentflow", + "target": "llmAgentflow_0", + "targetHandle": "llmAgentflow_0", + "data": { + "sourceColor": "#E4B7FF", + "targetColor": "#64B5F6", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "customFunctionAgentflow_0-customFunctionAgentflow_0-output-customFunctionAgentflow-llmAgentflow_0-llmAgentflow_0" + }, + { + "source": "llmAgentflow_0", + "sourceHandle": "llmAgentflow_0-output-llmAgentflow", + "target": "conditionAgentAgentflow_0", + "targetHandle": "conditionAgentAgentflow_0", + "data": { + "sourceColor": "#64B5F6", + "targetColor": "#ff8fab", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "llmAgentflow_0-llmAgentflow_0-output-llmAgentflow-conditionAgentAgentflow_0-conditionAgentAgentflow_0" + }, + { + "source": "conditionAgentAgentflow_0", + "sourceHandle": "conditionAgentAgentflow_0-output-0", + "target": "customFunctionAgentflow_1", + "targetHandle": "customFunctionAgentflow_1", + "data": { + "sourceColor": "#ff8fab", + "targetColor": "#E4B7FF", + "edgeLabel": "0", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "conditionAgentAgentflow_0-conditionAgentAgentflow_0-output-0-customFunctionAgentflow_1-customFunctionAgentflow_1" + }, + { + "source": "conditionAgentAgentflow_0", + "sourceHandle": "conditionAgentAgentflow_0-output-1", + "target": "loopAgentflow_0", + "targetHandle": "loopAgentflow_0", + "data": { + "sourceColor": "#ff8fab", + "targetColor": "#FFA07A", + "edgeLabel": "1", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "conditionAgentAgentflow_0-conditionAgentAgentflow_0-output-1-loopAgentflow_0-loopAgentflow_0" + }, + { + "source": "customFunctionAgentflow_1", + "sourceHandle": "customFunctionAgentflow_1-output-customFunctionAgentflow", + "target": "conditionAgentAgentflow_1", + "targetHandle": "conditionAgentAgentflow_1", + "data": { + "sourceColor": "#E4B7FF", + "targetColor": "#ff8fab", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "customFunctionAgentflow_1-customFunctionAgentflow_1-output-customFunctionAgentflow-conditionAgentAgentflow_1-conditionAgentAgentflow_1" + }, + { + "source": "conditionAgentAgentflow_1", + "sourceHandle": "conditionAgentAgentflow_1-output-0", + "target": "llmAgentflow_1", + "targetHandle": "llmAgentflow_1", + "data": { + "sourceColor": "#ff8fab", + "targetColor": "#64B5F6", + "edgeLabel": "0", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "conditionAgentAgentflow_1-conditionAgentAgentflow_1-output-0-llmAgentflow_1-llmAgentflow_1" + }, + { + "source": "conditionAgentAgentflow_1", + "sourceHandle": "conditionAgentAgentflow_1-output-1", + "target": "llmAgentflow_2", + "targetHandle": "llmAgentflow_2", + "data": { + "sourceColor": "#ff8fab", + "targetColor": "#64B5F6", + "edgeLabel": "1", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "conditionAgentAgentflow_1-conditionAgentAgentflow_1-output-1-llmAgentflow_2-llmAgentflow_2" + }, + { + "source": "llmAgentflow_2", + "sourceHandle": "llmAgentflow_2-output-llmAgentflow", + "target": "loopAgentflow_1", + "targetHandle": "loopAgentflow_1", + "data": { + "sourceColor": "#64B5F6", + "targetColor": "#FFA07A", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "llmAgentflow_2-llmAgentflow_2-output-llmAgentflow-loopAgentflow_1-loopAgentflow_1" + } + ] +} diff --git a/packages/server/marketplaces/agentflowsv2/Email Reply HITL Agent.json b/packages/server/marketplaces/agentflowsv2/Simple RAG.json similarity index 66% rename from packages/server/marketplaces/agentflowsv2/Email Reply HITL Agent.json rename to packages/server/marketplaces/agentflowsv2/Simple RAG.json index 2ab7e4d9..b37887c0 100644 --- a/packages/server/marketplaces/agentflowsv2/Email Reply HITL Agent.json +++ b/packages/server/marketplaces/agentflowsv2/Simple RAG.json @@ -1,13 +1,13 @@ { - "description": "An email reply HITL (human in the loop) agent that can proceed or refine the email with user input", - "usecases": ["Human In Loop"], + "description": "A basic RAG agent that can retrieve documents from document store and answer questions", + "usecases": ["Documents QnA"], "nodes": [ { "id": "startAgentflow_0", "type": "agentFlow", "position": { - "x": -212.0817769699585, - "y": 95.2304753249555 + "x": 64, + "y": 98.5 }, "data": { "id": "startAgentflow_0", @@ -133,7 +133,9 @@ "name": "startEphemeralMemory", "type": "boolean", "description": "Start fresh for every execution without past chat history", - "optional": true + "optional": true, + "id": "startAgentflow_0-input-startEphemeralMemory-boolean", + "display": true }, { "label": "Flow State", @@ -152,7 +154,8 @@ "label": "Value", "name": "value", "type": "string", - "placeholder": "Bar" + "placeholder": "Bar", + "optional": true } ], "id": "startAgentflow_0-input-startState-array", @@ -174,7 +177,9 @@ "formTitle": "", "formDescription": "", "formInputTypes": "", - "startState": "" + "startEphemeralMemory": "", + "startState": "", + "startPersistState": "" }, "outputAnchors": [ { @@ -186,24 +191,24 @@ "outputs": {}, "selected": false }, - "width": 101, - "height": 65, - "selected": false, + "width": 103, + "height": 66, "positionAbsolute": { - "x": -212.0817769699585, - "y": 95.2304753249555 + "x": 64, + "y": 98.5 }, + "selected": false, "dragging": false }, { "id": "agentAgentflow_0", "position": { - "x": -62.25, - "y": 76 + "x": 216.75, + "y": 96.5 }, "data": { "id": "agentAgentflow_0", - "label": "Email Reply Agent", + "label": "QnA", "version": 1, "name": "agentAgentflow", "type": "Agent", @@ -494,24 +499,18 @@ "agentMessages": [ { "role": "system", - "content": "

You are a customer support agent working in Flowise Inc. Write a professional email reply to user's query. Use the web search tools to get more details about the prospect.

" + "content": "

You are a helpful assistant. Using the provided context, answer the user's question to the best of your ability using the resources provided.

If there is nothing in the context relevant to the question at hand, just say \"Hmm, I'm not sure.\" Don't try to make up an answer.

" } ], - "agentTools": [ + "agentTools": "", + "agentKnowledgeDocumentStores": [ { - "agentSelectedTool": "googleCustomSearch", - "agentSelectedToolConfig": { - "agentSelectedTool": "googleCustomSearch" - } - }, - { - "agentSelectedTool": "currentDateTime", - "agentSelectedToolConfig": { - "agentSelectedTool": "currentDateTime" - } + "documentStore": "25429b8f-0377-4762-9cda-0d5366cf022c:AI-Paper", + "docStoreDescription": "This paper provides an extensive overview of artificial intelligence-generated content (AIGC), including its definition, capabilities, applications, challenges, and future directions, serving as a valuable resource for researchers and industry professionals to understand and harness AIGC's potential.", + "returnSourceDocuments": true } ], - "agentKnowledgeDocumentStores": "", + "agentKnowledgeVSEmbeddings": "", "agentEnableMemory": true, "agentMemoryType": "allMessages", "agentUserMessage": "", @@ -549,250 +548,64 @@ "selected": false }, "type": "agentFlow", - "width": 182, - "height": 103, + "width": 175, + "height": 72, "selected": false, "positionAbsolute": { - "x": -62.25, - "y": 76 + "x": 216.75, + "y": 96.5 }, "dragging": false }, { - "id": "humanInputAgentflow_0", + "id": "stickyNoteAgentflow_0", "position": { - "x": 156.05666363734434, - "y": 86.62266545493773 + "x": 209.875, + "y": -61.25 }, "data": { - "id": "humanInputAgentflow_0", - "label": "Human Input 0", + "id": "stickyNoteAgentflow_0", + "label": "Sticky Note", "version": 1, - "name": "humanInputAgentflow", - "type": "HumanInput", - "color": "#6E6EFD", - "baseClasses": ["HumanInput"], + "name": "stickyNoteAgentflow", + "type": "StickyNote", + "color": "#fee440", + "baseClasses": ["StickyNote"], "category": "Agent Flows", - "description": "Request human input, approval or rejection during execution", + "description": "Add notes to the agent flow", "inputParams": [ { - "label": "Description Type", - "name": "humanInputDescriptionType", - "type": "options", - "options": [ - { - "label": "Fixed", - "name": "fixed", - "description": "Specify a fixed description" - }, - { - "label": "Dynamic", - "name": "dynamic", - "description": "Use LLM to generate a description" - } - ], - "id": "humanInputAgentflow_0-input-humanInputDescriptionType-options", - "display": true - }, - { - "label": "Description", - "name": "humanInputDescription", + "label": "", + "name": "note", "type": "string", - "placeholder": "Are you sure you want to proceed?", - "acceptVariable": true, - "rows": 4, - "show": { - "humanInputDescriptionType": "fixed" - }, - "id": "humanInputAgentflow_0-input-humanInputDescription-string", - "display": true - }, - { - "label": "Model", - "name": "humanInputModel", - "type": "asyncOptions", - "loadMethod": "listModels", - "loadConfig": true, - "show": { - "humanInputDescriptionType": "dynamic" - }, - "id": "humanInputAgentflow_0-input-humanInputModel-asyncOptions", - "display": false - }, - { - "label": "Prompt", - "name": "humanInputModelPrompt", - "type": "string", - "default": "

Summarize the conversation between the user and the assistant, reiterate the last message from the assistant, and ask if user would like to proceed or if they have any feedback.

\n
    \n
  • Begin by capturing the key points of the conversation, ensuring that you reflect the main ideas and themes discussed.
  • \n
  • Then, clearly reproduce the last message sent by the assistant to maintain continuity. Make sure the whole message is reproduced.
  • \n
  • Finally, ask the user if they would like to proceed, or provide any feedback on the last assistant message
  • \n
\n

Output Format The output should be structured in three parts in text:

\n
    \n
  • A summary of the conversation (1-3 sentences).
  • \n
  • The last assistant message (exactly as it appeared).
  • \n
  • Ask the user if they would like to proceed, or provide any feedback on last assistant message. No other explanation and elaboration is needed.
  • \n
\n", - "acceptVariable": true, - "generateInstruction": true, - "rows": 4, - "show": { - "humanInputDescriptionType": "dynamic" - }, - "id": "humanInputAgentflow_0-input-humanInputModelPrompt-string", - "display": false - }, - { - "label": "Enable Feedback", - "name": "humanInputEnableFeedback", - "type": "boolean", - "default": true, - "id": "humanInputAgentflow_0-input-humanInputEnableFeedback-boolean", + "rows": 1, + "placeholder": "Type something here", + "optional": true, + "id": "stickyNoteAgentflow_0-input-note-string", "display": true } ], "inputAnchors": [], "inputs": { - "humanInputDescriptionType": "fixed", - "humanInputEnableFeedback": true, - "humanInputModelConfig": { - "cache": "", - "modelName": "gpt-4o-mini", - "temperature": 0.9, - "streaming": true, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "strictToolCalling": "", - "stopSequence": "", - "basepath": "", - "proxyUrl": "", - "baseOptions": "", - "allowImageUploads": "", - "imageResolution": "low", - "reasoningEffort": "medium", - "humanInputModel": "chatOpenAI" - }, - "humanInputDescription": "

Are you sure you want to proceed?

" + "note": "Agent can retrieve documents from upserted document store, and directly from vector database" }, "outputAnchors": [ { - "id": "humanInputAgentflow_0-output-0", - "label": "Human Input", - "name": "humanInputAgentflow" - }, - { - "id": "humanInputAgentflow_0-output-1", - "label": "Human Input", - "name": "humanInputAgentflow" + "id": "stickyNoteAgentflow_0-output-stickyNoteAgentflow", + "label": "Sticky Note", + "name": "stickyNoteAgentflow" } ], - "outputs": { - "humanInputAgentflow": "" - }, - "selected": false - }, - "type": "agentFlow", - "width": 161, - "height": 80, - "selected": false, - "positionAbsolute": { - "x": 156.05666363734434, - "y": 86.62266545493773 - }, - "dragging": false - }, - { - "id": "directReplyAgentflow_0", - "position": { - "x": 363.0101864947954, - "y": 35.15053748988734 - }, - "data": { - "id": "directReplyAgentflow_0", - "label": "Direct Reply 0", - "version": 1, - "name": "directReplyAgentflow", - "type": "DirectReply", - "color": "#4DDBBB", - "hideOutput": true, - "baseClasses": ["DirectReply"], - "category": "Agent Flows", - "description": "Directly reply to the user with a message", - "inputParams": [ - { - "label": "Message", - "name": "directReplyMessage", - "type": "string", - "rows": 4, - "acceptVariable": true, - "id": "directReplyAgentflow_0-input-directReplyMessage-string", - "display": true - } - ], - "inputAnchors": [], - "inputs": { - "directReplyMessage": "

{{ agentAgentflow_0 }}

" - }, - "outputAnchors": [], "outputs": {}, "selected": false }, - "type": "agentFlow", - "width": 155, - "height": 65, + "type": "stickyNote", + "width": 210, + "height": 143, "selected": false, "positionAbsolute": { - "x": 363.0101864947954, - "y": 35.15053748988734 - }, - "dragging": false - }, - { - "id": "loopAgentflow_0", - "position": { - "x": 366.5975521223236, - "y": 130.12266545493773 - }, - "data": { - "id": "loopAgentflow_0", - "label": "Loop 0", - "version": 1, - "name": "loopAgentflow", - "type": "Loop", - "color": "#FFA07A", - "hideOutput": true, - "baseClasses": ["Loop"], - "category": "Agent Flows", - "description": "Loop back to a previous node", - "inputParams": [ - { - "label": "Loop Back To", - "name": "loopBackToNode", - "type": "asyncOptions", - "loadMethod": "listPreviousNodes", - "freeSolo": true, - "id": "loopAgentflow_0-input-loopBackToNode-asyncOptions", - "display": true - }, - { - "label": "Max Loop Count", - "name": "maxLoopCount", - "type": "number", - "default": 5, - "id": "loopAgentflow_0-input-maxLoopCount-number", - "display": true - } - ], - "inputAnchors": [], - "inputs": { - "loopBackToNode": "agentAgentflow_0-Email Reply Agent", - "maxLoopCount": 5 - }, - "outputAnchors": [], - "outputs": {}, - "selected": false - }, - "type": "agentFlow", - "width": 113, - "height": 65, - "selected": false, - "positionAbsolute": { - "x": 366.5975521223236, - "y": 130.12266545493773 + "x": 209.875, + "y": -61.25 }, "dragging": false } @@ -810,47 +623,6 @@ }, "type": "agentFlow", "id": "startAgentflow_0-startAgentflow_0-output-startAgentflow-agentAgentflow_0-agentAgentflow_0" - }, - { - "source": "agentAgentflow_0", - "sourceHandle": "agentAgentflow_0-output-agentAgentflow", - "target": "humanInputAgentflow_0", - "targetHandle": "humanInputAgentflow_0", - "data": { - "sourceColor": "#4DD0E1", - "targetColor": "#6E6EFD", - "isHumanInput": false - }, - "type": "agentFlow", - "id": "agentAgentflow_0-agentAgentflow_0-output-agentAgentflow-humanInputAgentflow_0-humanInputAgentflow_0" - }, - { - "source": "humanInputAgentflow_0", - "sourceHandle": "humanInputAgentflow_0-output-0", - "target": "directReplyAgentflow_0", - "targetHandle": "directReplyAgentflow_0", - "data": { - "sourceColor": "#6E6EFD", - "targetColor": "#4DDBBB", - "edgeLabel": "proceed", - "isHumanInput": true - }, - "type": "agentFlow", - "id": "humanInputAgentflow_0-humanInputAgentflow_0-output-0-directReplyAgentflow_0-directReplyAgentflow_0" - }, - { - "source": "humanInputAgentflow_0", - "sourceHandle": "humanInputAgentflow_0-output-1", - "target": "loopAgentflow_0", - "targetHandle": "loopAgentflow_0", - "data": { - "sourceColor": "#6E6EFD", - "targetColor": "#FFA07A", - "edgeLabel": "reject", - "isHumanInput": true - }, - "type": "agentFlow", - "id": "humanInputAgentflow_0-humanInputAgentflow_0-output-1-loopAgentflow_0-loopAgentflow_0" } ] } diff --git a/packages/server/marketplaces/agentflowsv2/Structured Output.json b/packages/server/marketplaces/agentflowsv2/Structured Output.json new file mode 100644 index 00000000..d6de0e7c --- /dev/null +++ b/packages/server/marketplaces/agentflowsv2/Structured Output.json @@ -0,0 +1,549 @@ +{ + "description": "Return structured output from LLM", + "usecases": ["Extraction"], + "nodes": [ + { + "id": "startAgentflow_0", + "type": "agentFlow", + "position": { + "x": 64, + "y": 98.5 + }, + "data": { + "id": "startAgentflow_0", + "label": "Start", + "version": 1.1, + "name": "startAgentflow", + "type": "Start", + "color": "#7EE787", + "hideInput": true, + "baseClasses": ["Start"], + "category": "Agent Flows", + "description": "Starting point of the agentflow", + "inputParams": [ + { + "label": "Input Type", + "name": "startInputType", + "type": "options", + "options": [ + { + "label": "Chat Input", + "name": "chatInput", + "description": "Start the conversation with chat input" + }, + { + "label": "Form Input", + "name": "formInput", + "description": "Start the workflow with form inputs" + } + ], + "default": "chatInput", + "id": "startAgentflow_0-input-startInputType-options", + "display": true + }, + { + "label": "Form Title", + "name": "formTitle", + "type": "string", + "placeholder": "Please Fill Out The Form", + "show": { + "startInputType": "formInput" + }, + "id": "startAgentflow_0-input-formTitle-string", + "display": false + }, + { + "label": "Form Description", + "name": "formDescription", + "type": "string", + "placeholder": "Complete all fields below to continue", + "show": { + "startInputType": "formInput" + }, + "id": "startAgentflow_0-input-formDescription-string", + "display": false + }, + { + "label": "Form Input Types", + "name": "formInputTypes", + "description": "Specify the type of form input", + "type": "array", + "show": { + "startInputType": "formInput" + }, + "array": [ + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Options", + "name": "options" + } + ], + "default": "string" + }, + { + "label": "Label", + "name": "label", + "type": "string", + "placeholder": "Label for the input" + }, + { + "label": "Variable Name", + "name": "name", + "type": "string", + "placeholder": "Variable name for the input (must be camel case)", + "description": "Variable name must be camel case. For example: firstName, lastName, etc." + }, + { + "label": "Add Options", + "name": "addOptions", + "type": "array", + "show": { + "formInputTypes[$index].type": "options" + }, + "array": [ + { + "label": "Option", + "name": "option", + "type": "string" + } + ] + } + ], + "id": "startAgentflow_0-input-formInputTypes-array", + "display": false + }, + { + "label": "Ephemeral Memory", + "name": "startEphemeralMemory", + "type": "boolean", + "description": "Start fresh for every execution without past chat history", + "optional": true, + "id": "startAgentflow_0-input-startEphemeralMemory-boolean", + "display": true + }, + { + "label": "Flow State", + "name": "startState", + "description": "Runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string", + "placeholder": "Foo" + }, + { + "label": "Value", + "name": "value", + "type": "string", + "placeholder": "Bar", + "optional": true + } + ], + "id": "startAgentflow_0-input-startState-array", + "display": true + }, + { + "label": "Persist State", + "name": "startPersistState", + "type": "boolean", + "description": "Persist the state in the same session", + "optional": true, + "id": "startAgentflow_0-input-startPersistState-boolean", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "startInputType": "chatInput", + "formTitle": "", + "formDescription": "", + "formInputTypes": "", + "startEphemeralMemory": "", + "startState": "", + "startPersistState": "" + }, + "outputAnchors": [ + { + "id": "startAgentflow_0-output-startAgentflow", + "label": "Start", + "name": "startAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "width": 103, + "height": 66, + "positionAbsolute": { + "x": 64, + "y": 98.5 + }, + "selected": false, + "dragging": false + }, + { + "id": "llmAgentflow_0", + "position": { + "x": 234.5, + "y": 95.75 + }, + "data": { + "id": "llmAgentflow_0", + "label": "Strutured Output", + "version": 1, + "name": "llmAgentflow", + "type": "LLM", + "color": "#64B5F6", + "baseClasses": ["LLM"], + "category": "Agent Flows", + "description": "Large language models to analyze user-provided inputs and generate responses", + "inputParams": [ + { + "label": "Model", + "name": "llmModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "llmAgentflow_0-input-llmModel-asyncOptions", + "display": true + }, + { + "label": "Messages", + "name": "llmMessages", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Role", + "name": "role", + "type": "options", + "options": [ + { + "label": "System", + "name": "system" + }, + { + "label": "Assistant", + "name": "assistant" + }, + { + "label": "Developer", + "name": "developer" + }, + { + "label": "User", + "name": "user" + } + ] + }, + { + "label": "Content", + "name": "content", + "type": "string", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4 + } + ], + "id": "llmAgentflow_0-input-llmMessages-array", + "display": true + }, + { + "label": "Enable Memory", + "name": "llmEnableMemory", + "type": "boolean", + "description": "Enable memory for the conversation thread", + "default": true, + "optional": true, + "id": "llmAgentflow_0-input-llmEnableMemory-boolean", + "display": true + }, + { + "label": "Memory Type", + "name": "llmMemoryType", + "type": "options", + "options": [ + { + "label": "All Messages", + "name": "allMessages", + "description": "Retrieve all messages from the conversation" + }, + { + "label": "Window Size", + "name": "windowSize", + "description": "Uses a fixed window size to surface the last N messages" + }, + { + "label": "Conversation Summary", + "name": "conversationSummary", + "description": "Summarizes the whole conversation" + }, + { + "label": "Conversation Summary Buffer", + "name": "conversationSummaryBuffer", + "description": "Summarize conversations once token limit is reached. Default to 2000" + } + ], + "optional": true, + "default": "allMessages", + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_0-input-llmMemoryType-options", + "display": false + }, + { + "label": "Window Size", + "name": "llmMemoryWindowSize", + "type": "number", + "default": "20", + "description": "Uses a fixed window size to surface the last N messages", + "show": { + "llmMemoryType": "windowSize" + }, + "id": "llmAgentflow_0-input-llmMemoryWindowSize-number", + "display": false + }, + { + "label": "Max Token Limit", + "name": "llmMemoryMaxTokenLimit", + "type": "number", + "default": "2000", + "description": "Summarize conversations once token limit is reached. Default to 2000", + "show": { + "llmMemoryType": "conversationSummaryBuffer" + }, + "id": "llmAgentflow_0-input-llmMemoryMaxTokenLimit-number", + "display": false + }, + { + "label": "Input Message", + "name": "llmUserMessage", + "type": "string", + "description": "Add an input message as user message at the end of the conversation", + "rows": 4, + "optional": true, + "acceptVariable": true, + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_0-input-llmUserMessage-string", + "display": false + }, + { + "label": "Return Response As", + "name": "llmReturnResponseAs", + "type": "options", + "options": [ + { + "label": "User Message", + "name": "userMessage" + }, + { + "label": "Assistant Message", + "name": "assistantMessage" + } + ], + "default": "userMessage", + "id": "llmAgentflow_0-input-llmReturnResponseAs-options", + "display": true + }, + { + "label": "JSON Structured Output", + "name": "llmStructuredOutput", + "description": "Instruct the LLM to give output in a JSON structured schema", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string" + }, + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "String Array", + "name": "stringArray" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Enum", + "name": "enum" + }, + { + "label": "JSON Array", + "name": "jsonArray" + } + ] + }, + { + "label": "Enum Values", + "name": "enumValues", + "type": "string", + "placeholder": "value1, value2, value3", + "description": "Enum values. Separated by comma", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "enum" + } + }, + { + "label": "JSON Schema", + "name": "jsonSchema", + "type": "code", + "placeholder": "{\n \"answer\": {\n \"type\": \"string\",\n \"description\": \"Value of the answer\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"description\": \"Reason for the answer\"\n },\n \"optional\": {\n \"type\": \"boolean\"\n },\n \"count\": {\n \"type\": \"number\"\n },\n \"children\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\",\n \"description\": \"Value of the children's answer\"\n }\n }\n }\n }\n}", + "description": "JSON schema for the structured output", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "jsonArray" + } + }, + { + "label": "Description", + "name": "description", + "type": "string", + "placeholder": "Description of the key" + } + ], + "id": "llmAgentflow_0-input-llmStructuredOutput-array", + "display": true + }, + { + "label": "Update Flow State", + "name": "llmUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "llmAgentflow_0-input-llmUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "llmModel": "chatAnthropic", + "llmMessages": [ + { + "role": "system", + "content": "

Given user query, return result only in JSON format, without exception.

When asked to self-correct, output only the corrected JSON and no other text.

" + }, + { + "role": "user", + "content": "

{{ question }}

" + } + ], + "llmEnableMemory": false, + "llmReturnResponseAs": "userMessage", + "llmStructuredOutput": [ + { + "key": "output", + "type": "jsonArray", + "enumValues": "", + "jsonSchema": "{\n \"answer\": {\n \"type\": \"string\",\n \"description\": \"Value of the answer\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"description\": \"Reason for the answer\"\n }\n}", + "description": "answer and its reason to the question" + } + ], + "llmUpdateState": "", + "llmModelConfig": { + "credential": "", + "modelName": "claude-sonnet-4-0", + "temperature": 0.9, + "streaming": true, + "maxTokensToSample": "", + "topP": "", + "topK": "", + "extendedThinking": "", + "budgetTokens": 1024, + "allowImageUploads": "", + "llmModel": "chatAnthropic" + } + }, + "outputAnchors": [ + { + "id": "llmAgentflow_0-output-llmAgentflow", + "label": "LLM", + "name": "llmAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 213, + "height": 72, + "selected": false, + "positionAbsolute": { + "x": 234.5, + "y": 95.75 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "startAgentflow_0", + "sourceHandle": "startAgentflow_0-output-startAgentflow", + "target": "llmAgentflow_0", + "targetHandle": "llmAgentflow_0", + "data": { + "sourceColor": "#7EE787", + "targetColor": "#64B5F6", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "startAgentflow_0-startAgentflow_0-output-startAgentflow-llmAgentflow_0-llmAgentflow_0" + } + ] +} diff --git a/packages/server/marketplaces/agentflowsv2/Supervisor Worker.json b/packages/server/marketplaces/agentflowsv2/Supervisor Worker.json index 1773ce6a..510b820c 100644 --- a/packages/server/marketplaces/agentflowsv2/Supervisor Worker.json +++ b/packages/server/marketplaces/agentflowsv2/Supervisor Worker.json @@ -6,8 +6,8 @@ "id": "startAgentflow_0", "type": "agentFlow", "position": { - "x": -234.25083179589828, - "y": 89.8928676312403 + "x": -198.4357561998925, + "y": 90.62378754136287 }, "data": { "id": "startAgentflow_0", @@ -195,12 +195,12 @@ "outputs": {}, "selected": false }, - "width": 101, - "height": 65, + "width": 103, + "height": 66, "selected": false, "positionAbsolute": { - "x": -234.25083179589828, - "y": 89.8928676312403 + "x": -198.4357561998925, + "y": 90.62378754136287 }, "dragging": false }, @@ -483,7 +483,7 @@ "selected": false }, "type": "agentFlow", - "width": 184, + "width": 194, "height": 100, "selected": false, "positionAbsolute": { @@ -787,11 +787,11 @@ ], "inputAnchors": [], "inputs": { - "agentModel": "azureChatOpenAI", + "agentModel": "chatOpenAI", "agentMessages": [ { "role": "system", - "content": "

As a Senior Software Engineer, you are a pivotal part of our innovative development team. Your expertise and leadership drive the creation of robust, scalable software solutions that meet the needs of our diverse clientele. By applying best practices in software development, you ensure that our products are reliable, efficient, and maintainable.

Your goal is to lead the development of high-quality software solutions.

Utilize your deep technical knowledge and experience to architect, design, and implement software systems that address complex problems. Collaborate closely with other engineers, reviewers to ensure that the solutions you develop align with business objectives and user needs.

Design and implement new feature for the given task, ensuring it integrates seamlessly with existing systems and meets performance requirements. Use your understanding of {technology} to build this feature. Make sure to adhere to our coding standards and follow best practices.

The output should be a fully functional, well-documented feature that enhances our product's capabilities. Include detailed comments in the code. Pass the code to Quality Assurance Engineer for review if neccessary. Once ther review is good enough, produce a finalized version of the code.

" + "content": "

As a Senior Software Engineer, you are a pivotal part of our innovative development team. Your expertise and leadership drive the creation of robust, scalable software solutions that meet the needs of our diverse clientele. By applying best practices in software development, you ensure that our products are reliable, efficient, and maintainable.

Your goal is to lead the development of high-quality software solutions.

Utilize your deep technical knowledge and experience to architect, design, and implement software systems that address complex problems. Collaborate closely with other engineers, reviewers to ensure that the solutions you develop align with business objectives and user needs.

Design and implement new feature for the given task, ensuring it integrates seamlessly with existing systems and meets performance requirements. Use your understanding of React, Tailwindcss, NodeJS to build this feature. Make sure to adhere to our coding standards and follow best practices.

The output should be a fully functional, well-documented feature that enhances our product's capabilities. Include detailed comments in the code.

" } ], "agentTools": "", @@ -803,20 +803,23 @@ "agentUpdateState": "", "agentModelConfig": { "credential": "", - "modelName": "gpt-4.1", + "modelName": "gpt-4o-mini", "temperature": 0.9, - "maxTokens": "", "streaming": true, + "maxTokens": "", "topP": "", "frequencyPenalty": "", "presencePenalty": "", "timeout": "", + "strictToolCalling": "", + "stopSequence": "", "basepath": "", + "proxyUrl": "", "baseOptions": "", "allowImageUploads": "", "imageResolution": "low", "reasoningEffort": "medium", - "agentModel": "azureChatOpenAI" + "agentModel": "chatOpenAI" } }, "outputAnchors": [ @@ -830,8 +833,8 @@ "selected": false }, "type": "agentFlow", - "width": 183, - "height": 71, + "width": 191, + "height": 72, "selected": false, "positionAbsolute": { "x": 352.5679347768288, @@ -842,8 +845,8 @@ { "id": "agentAgentflow_2", "position": { - "x": 358.5981605238689, - "y": 87.38558154725587 + "x": 359.32908043399146, + "y": 88.11650145737843 }, "data": { "id": "agentAgentflow_2", @@ -1134,11 +1137,11 @@ ], "inputAnchors": [], "inputs": { - "agentModel": "chatDeepseek", + "agentModel": "chatOpenAI", "agentMessages": [ { "role": "system", - "content": "

As a Quality Assurance Engineer, you are an integral part of our development team, ensuring that our software products are of the highest quality. Your meticulous attention to detail and expertise in testing methodologies are crucial in identifying defects and ensuring that our code meets the highest standards.

Your goal is to ensure the delivery of high-quality software through thorough code review and testing.

Review the codebase for the new feature designed and implemented by the Senior Software Engineer. Your expertise goes beyond mere code inspection; you are adept at ensuring that developments not only function as intended but also adhere to the team's coding standards, enhance maintainability, and seamlessly integrate with existing systems.

With a deep appreciation for collaborative development, you provide constructive feedback, guiding contributors towards best practices and fostering a culture of continuous improvement. Your meticulous approach to reviewing code, coupled with your ability to foresee potential issues and recommend proactive solutions, ensures the delivery of high-quality software that is robust, scalable, and aligned with the team's strategic goals.

Always pass back the review and feedback to Senior Software Engineer.

" + "content": "

As a Quality Assurance Engineer, you are an integral part of our development team, ensuring that our software products are of the highest quality. Your meticulous attention to detail and expertise in testing methodologies are crucial in identifying defects and ensuring that our code meets the highest standards.

Your goal is to ensure the delivery of high-quality software through thorough code review and testing.

Review the codebase for the new feature designed and implemented by the Senior Software Engineer. Your expertise goes beyond mere code inspection; you are adept at ensuring that developments not only function as intended but also adhere to the team's coding standards, enhance maintainability, and seamlessly integrate with existing systems.

With a deep appreciation for collaborative development, you provide constructive feedback, guiding contributors towards best practices and fostering a culture of continuous improvement. Your meticulous approach to reviewing code, coupled with your ability to foresee potential issues and recommend proactive solutions, ensures the delivery of high-quality software that is robust, scalable, and aligned with the team's strategic goals.

" } ], "agentTools": "", @@ -1150,17 +1153,23 @@ "agentUpdateState": "", "agentModelConfig": { "credential": "", - "modelName": "deepseek-reasoner", - "temperature": 0.7, + "modelName": "gpt-4o-mini", + "temperature": 0.9, "streaming": true, "maxTokens": "", "topP": "", "frequencyPenalty": "", "presencePenalty": "", "timeout": "", + "strictToolCalling": "", "stopSequence": "", + "basepath": "", + "proxyUrl": "", "baseOptions": "", - "agentModel": "chatDeepseek" + "allowImageUploads": "", + "imageResolution": "low", + "reasoningEffort": "medium", + "agentModel": "chatOpenAI" } }, "outputAnchors": [ @@ -1174,12 +1183,12 @@ "selected": false }, "type": "agentFlow", - "width": 206, - "height": 71, + "width": 175, + "height": 72, "selected": false, "positionAbsolute": { - "x": 358.5981605238689, - "y": 87.38558154725587 + "x": 359.32908043399146, + "y": 88.11650145737843 }, "dragging": false }, @@ -1478,27 +1487,29 @@ ], "inputAnchors": [], "inputs": { - "agentModel": "chatAnthropic", + "agentModel": "chatGoogleGenerativeAI", "agentMessages": "", "agentTools": "", "agentKnowledgeDocumentStores": "", "agentEnableMemory": true, "agentMemoryType": "allMessages", - "agentUserMessage": "

Given the above conversations, generate a detail solution developed by the software engineer and code reviewer. Include full code, improvements and review.

", + "agentUserMessage": "

Given the above conversations, generate a detail solution developed by the software engineer and code reviewer.

Your guiding principles:

  1. Preserve Full Context
    Include all code implementations, improvements and review from the conversation. Do not omit, summarize, or oversimplify key information.

  2. Markdown Output Only
    Your final output must be in Markdown format.

", "agentReturnResponseAs": "userMessage", "agentUpdateState": "", "agentModelConfig": { "credential": "", - "modelName": "claude-3-7-sonnet-latest", + "modelName": "gemini-2.5-flash-preview-05-20", + "customModelName": "", "temperature": 0.9, "streaming": true, - "maxTokensToSample": "", + "maxOutputTokens": "", "topP": "", "topK": "", - "extendedThinking": "", - "budgetTokens": 1024, + "harmCategory": "", + "harmBlockThreshold": "", + "baseUrl": "", "allowImageUploads": "", - "agentModel": "chatAnthropic" + "agentModel": "chatGoogleGenerativeAI" } }, "outputAnchors": [ @@ -1512,8 +1523,8 @@ "selected": false }, "type": "agentFlow", - "width": 231, - "height": 71, + "width": 283, + "height": 72, "selected": false, "positionAbsolute": { "x": 357.60470406099364, @@ -1524,8 +1535,8 @@ { "id": "loopAgentflow_0", "position": { - "x": 574.050701666824, - "y": -20.0960840521807 + "x": 572.5888618465789, + "y": -20.827003962303266 }, "data": { "id": "loopAgentflow_0", @@ -1567,20 +1578,20 @@ "selected": false }, "type": "agentFlow", - "width": 186, - "height": 65, + "width": 195, + "height": 66, "selected": false, "dragging": false, "positionAbsolute": { - "x": 574.050701666824, - "y": -20.0960840521807 + "x": 572.5888618465789, + "y": -20.827003962303266 } }, { "id": "loopAgentflow_1", "position": { - "x": 600.379151793432, - "y": 90.25732743474846 + "x": 566.7568359277939, + "y": 90.98824734487103 }, "data": { "id": "loopAgentflow_1", @@ -1622,20 +1633,20 @@ "selected": false }, "type": "agentFlow", - "width": 186, - "height": 65, + "width": 195, + "height": 66, "selected": false, "dragging": false, "positionAbsolute": { - "x": 600.379151793432, - "y": 90.25732743474846 + "x": 566.7568359277939, + "y": 90.98824734487103 } }, { "id": "llmAgentflow_0", "position": { - "x": -78.28788541792727, - "y": 87.1528514813091 + "x": -60.01488766486309, + "y": 87.88377139143167 }, "data": { "id": "llmAgentflow_0", @@ -1950,7 +1961,7 @@ ], "llmModelConfig": { "cache": "", - "modelName": "gpt-4o-mini", + "modelName": "gpt-4.1", "temperature": 0.9, "streaming": true, "maxTokens": "", @@ -1964,7 +1975,6 @@ "proxyUrl": "", "baseOptions": "", "allowImageUploads": "", - "imageResolution": "low", "reasoningEffort": "medium", "llmModel": "chatOpenAI" } @@ -1980,12 +1990,12 @@ "selected": false }, "type": "agentFlow", - "width": 168, - "height": 71, + "width": 148, + "height": 72, "selected": false, "positionAbsolute": { - "x": -78.28788541792727, - "y": 87.1528514813091 + "x": -60.01488766486309, + "y": 87.88377139143167 }, "dragging": false } diff --git a/packages/server/marketplaces/agentflowsv2/Translator.json b/packages/server/marketplaces/agentflowsv2/Translator.json new file mode 100644 index 00000000..6d29804e --- /dev/null +++ b/packages/server/marketplaces/agentflowsv2/Translator.json @@ -0,0 +1,544 @@ +{ + "description": "Translate text from one language to another", + "usecases": ["Basic"], + "nodes": [ + { + "id": "startAgentflow_0", + "type": "agentFlow", + "position": { + "x": 64, + "y": 98.5 + }, + "data": { + "id": "startAgentflow_0", + "label": "Start", + "version": 1.1, + "name": "startAgentflow", + "type": "Start", + "color": "#7EE787", + "hideInput": true, + "baseClasses": ["Start"], + "category": "Agent Flows", + "description": "Starting point of the agentflow", + "inputParams": [ + { + "label": "Input Type", + "name": "startInputType", + "type": "options", + "options": [ + { + "label": "Chat Input", + "name": "chatInput", + "description": "Start the conversation with chat input" + }, + { + "label": "Form Input", + "name": "formInput", + "description": "Start the workflow with form inputs" + } + ], + "default": "chatInput", + "id": "startAgentflow_0-input-startInputType-options", + "display": true + }, + { + "label": "Form Title", + "name": "formTitle", + "type": "string", + "placeholder": "Please Fill Out The Form", + "show": { + "startInputType": "formInput" + }, + "id": "startAgentflow_0-input-formTitle-string", + "display": false + }, + { + "label": "Form Description", + "name": "formDescription", + "type": "string", + "placeholder": "Complete all fields below to continue", + "show": { + "startInputType": "formInput" + }, + "id": "startAgentflow_0-input-formDescription-string", + "display": false + }, + { + "label": "Form Input Types", + "name": "formInputTypes", + "description": "Specify the type of form input", + "type": "array", + "show": { + "startInputType": "formInput" + }, + "array": [ + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Options", + "name": "options" + } + ], + "default": "string" + }, + { + "label": "Label", + "name": "label", + "type": "string", + "placeholder": "Label for the input" + }, + { + "label": "Variable Name", + "name": "name", + "type": "string", + "placeholder": "Variable name for the input (must be camel case)", + "description": "Variable name must be camel case. For example: firstName, lastName, etc." + }, + { + "label": "Add Options", + "name": "addOptions", + "type": "array", + "show": { + "formInputTypes[$index].type": "options" + }, + "array": [ + { + "label": "Option", + "name": "option", + "type": "string" + } + ] + } + ], + "id": "startAgentflow_0-input-formInputTypes-array", + "display": false + }, + { + "label": "Ephemeral Memory", + "name": "startEphemeralMemory", + "type": "boolean", + "description": "Start fresh for every execution without past chat history", + "optional": true, + "id": "startAgentflow_0-input-startEphemeralMemory-boolean", + "display": true + }, + { + "label": "Flow State", + "name": "startState", + "description": "Runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string", + "placeholder": "Foo" + }, + { + "label": "Value", + "name": "value", + "type": "string", + "placeholder": "Bar", + "optional": true + } + ], + "id": "startAgentflow_0-input-startState-array", + "display": true + }, + { + "label": "Persist State", + "name": "startPersistState", + "type": "boolean", + "description": "Persist the state in the same session", + "optional": true, + "id": "startAgentflow_0-input-startPersistState-boolean", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "startInputType": "chatInput", + "formTitle": "", + "formDescription": "", + "formInputTypes": "", + "startEphemeralMemory": "", + "startState": "", + "startPersistState": "" + }, + "outputAnchors": [ + { + "id": "startAgentflow_0-output-startAgentflow", + "label": "Start", + "name": "startAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "width": 103, + "height": 66, + "positionAbsolute": { + "x": 64, + "y": 98.5 + }, + "selected": false, + "dragging": false + }, + { + "id": "llmAgentflow_0", + "position": { + "x": 234.5, + "y": 96.25 + }, + "data": { + "id": "llmAgentflow_0", + "label": "Translator", + "version": 1, + "name": "llmAgentflow", + "type": "LLM", + "color": "#64B5F6", + "baseClasses": ["LLM"], + "category": "Agent Flows", + "description": "Large language models to analyze user-provided inputs and generate responses", + "inputParams": [ + { + "label": "Model", + "name": "llmModel", + "type": "asyncOptions", + "loadMethod": "listModels", + "loadConfig": true, + "id": "llmAgentflow_0-input-llmModel-asyncOptions", + "display": true + }, + { + "label": "Messages", + "name": "llmMessages", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Role", + "name": "role", + "type": "options", + "options": [ + { + "label": "System", + "name": "system" + }, + { + "label": "Assistant", + "name": "assistant" + }, + { + "label": "Developer", + "name": "developer" + }, + { + "label": "User", + "name": "user" + } + ] + }, + { + "label": "Content", + "name": "content", + "type": "string", + "acceptVariable": true, + "generateInstruction": true, + "rows": 4 + } + ], + "id": "llmAgentflow_0-input-llmMessages-array", + "display": true + }, + { + "label": "Enable Memory", + "name": "llmEnableMemory", + "type": "boolean", + "description": "Enable memory for the conversation thread", + "default": true, + "optional": true, + "id": "llmAgentflow_0-input-llmEnableMemory-boolean", + "display": true + }, + { + "label": "Memory Type", + "name": "llmMemoryType", + "type": "options", + "options": [ + { + "label": "All Messages", + "name": "allMessages", + "description": "Retrieve all messages from the conversation" + }, + { + "label": "Window Size", + "name": "windowSize", + "description": "Uses a fixed window size to surface the last N messages" + }, + { + "label": "Conversation Summary", + "name": "conversationSummary", + "description": "Summarizes the whole conversation" + }, + { + "label": "Conversation Summary Buffer", + "name": "conversationSummaryBuffer", + "description": "Summarize conversations once token limit is reached. Default to 2000" + } + ], + "optional": true, + "default": "allMessages", + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_0-input-llmMemoryType-options", + "display": false + }, + { + "label": "Window Size", + "name": "llmMemoryWindowSize", + "type": "number", + "default": "20", + "description": "Uses a fixed window size to surface the last N messages", + "show": { + "llmMemoryType": "windowSize" + }, + "id": "llmAgentflow_0-input-llmMemoryWindowSize-number", + "display": false + }, + { + "label": "Max Token Limit", + "name": "llmMemoryMaxTokenLimit", + "type": "number", + "default": "2000", + "description": "Summarize conversations once token limit is reached. Default to 2000", + "show": { + "llmMemoryType": "conversationSummaryBuffer" + }, + "id": "llmAgentflow_0-input-llmMemoryMaxTokenLimit-number", + "display": false + }, + { + "label": "Input Message", + "name": "llmUserMessage", + "type": "string", + "description": "Add an input message as user message at the end of the conversation", + "rows": 4, + "optional": true, + "acceptVariable": true, + "show": { + "llmEnableMemory": true + }, + "id": "llmAgentflow_0-input-llmUserMessage-string", + "display": false + }, + { + "label": "Return Response As", + "name": "llmReturnResponseAs", + "type": "options", + "options": [ + { + "label": "User Message", + "name": "userMessage" + }, + { + "label": "Assistant Message", + "name": "assistantMessage" + } + ], + "default": "userMessage", + "id": "llmAgentflow_0-input-llmReturnResponseAs-options", + "display": true + }, + { + "label": "JSON Structured Output", + "name": "llmStructuredOutput", + "description": "Instruct the LLM to give output in a JSON structured schema", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "string" + }, + { + "label": "Type", + "name": "type", + "type": "options", + "options": [ + { + "label": "String", + "name": "string" + }, + { + "label": "String Array", + "name": "stringArray" + }, + { + "label": "Number", + "name": "number" + }, + { + "label": "Boolean", + "name": "boolean" + }, + { + "label": "Enum", + "name": "enum" + }, + { + "label": "JSON Array", + "name": "jsonArray" + } + ] + }, + { + "label": "Enum Values", + "name": "enumValues", + "type": "string", + "placeholder": "value1, value2, value3", + "description": "Enum values. Separated by comma", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "enum" + } + }, + { + "label": "JSON Schema", + "name": "jsonSchema", + "type": "code", + "placeholder": "{\n \"answer\": {\n \"type\": \"string\",\n \"description\": \"Value of the answer\"\n },\n \"reason\": {\n \"type\": \"string\",\n \"description\": \"Reason for the answer\"\n },\n \"optional\": {\n \"type\": \"boolean\"\n },\n \"count\": {\n \"type\": \"number\"\n },\n \"children\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"type\": \"string\",\n \"description\": \"Value of the children's answer\"\n }\n }\n }\n }\n}", + "description": "JSON schema for the structured output", + "optional": true, + "show": { + "llmStructuredOutput[$index].type": "jsonArray" + } + }, + { + "label": "Description", + "name": "description", + "type": "string", + "placeholder": "Description of the key" + } + ], + "id": "llmAgentflow_0-input-llmStructuredOutput-array", + "display": true + }, + { + "label": "Update Flow State", + "name": "llmUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "llmAgentflow_0-input-llmUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "llmModel": "chatGoogleGenerativeAI", + "llmMessages": [ + { + "role": "system", + "content": "

You are a helpful assistant that translates English to Japanese language. Return only Japanese language

" + }, + { + "role": "user", + "content": "

English:

{{ question }}

Japanese:

" + } + ], + "llmEnableMemory": false, + "llmReturnResponseAs": "userMessage", + "llmStructuredOutput": "", + "llmUpdateState": "", + "llmModelConfig": { + "cache": "", + "contextCache": "", + "modelName": "gemini-2.0-flash", + "customModelName": "", + "temperature": 0.9, + "streaming": true, + "maxOutputTokens": "", + "topP": "", + "topK": "", + "harmCategory": "", + "harmBlockThreshold": "", + "baseUrl": "", + "allowImageUploads": "", + "llmModel": "chatGoogleGenerativeAI" + } + }, + "outputAnchors": [ + { + "id": "llmAgentflow_0-output-llmAgentflow", + "label": "LLM", + "name": "llmAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 200, + "height": 72, + "selected": false, + "positionAbsolute": { + "x": 234.5, + "y": 96.25 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "startAgentflow_0", + "sourceHandle": "startAgentflow_0-output-startAgentflow", + "target": "llmAgentflow_0", + "targetHandle": "llmAgentflow_0", + "data": { + "sourceColor": "#7EE787", + "targetColor": "#64B5F6", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "startAgentflow_0-startAgentflow_0-output-startAgentflow-llmAgentflow_0-llmAgentflow_0" + } + ] +} diff --git a/packages/server/marketplaces/agentflowsv2/Slack Agent.json b/packages/server/marketplaces/agentflowsv2/Workplace Chat.json similarity index 81% rename from packages/server/marketplaces/agentflowsv2/Slack Agent.json rename to packages/server/marketplaces/agentflowsv2/Workplace Chat.json index a36876f8..3fce5322 100644 --- a/packages/server/marketplaces/agentflowsv2/Slack Agent.json +++ b/packages/server/marketplaces/agentflowsv2/Workplace Chat.json @@ -1,5 +1,5 @@ { - "description": "An agent that can post message to Slack channel", + "description": "An agent that can post AI responses to Workplace channels like Slack and Teams", "usecases": ["Agent"], "nodes": [ { @@ -186,8 +186,8 @@ "outputs": {}, "selected": false }, - "width": 101, - "height": 65, + "width": 103, + "height": 66, "selected": false, "positionAbsolute": { "x": -192.5, @@ -508,8 +508,8 @@ "selected": false }, "type": "agentFlow", - "width": 168, - "height": 71, + "width": 175, + "height": 72, "selected": false, "positionAbsolute": { "x": -31.25, @@ -520,12 +520,12 @@ { "id": "toolAgentflow_0", "position": { - "x": 182.75, - "y": 64.5 + "x": 181.67112630208328, + "y": 28.357731119791666 }, "data": { "id": "toolAgentflow_0", - "label": "Slack Reply", + "label": "Post to Slack", "version": 1.1, "name": "toolAgentflow", "type": "Tool", @@ -627,20 +627,20 @@ "selected": false }, "type": "agentFlow", - "width": 142, - "height": 71, + "width": 156, + "height": 68, "selected": false, "positionAbsolute": { - "x": 182.75, - "y": 64.5 + "x": 181.67112630208328, + "y": 28.357731119791666 }, "dragging": false }, { "id": "directReplyAgentflow_0", "position": { - "x": 366.75, - "y": 67.5 + "x": 373.22324218750003, + "y": 66.96056315104161 }, "data": { "id": "directReplyAgentflow_0", @@ -673,12 +673,138 @@ "selected": false }, "type": "agentFlow", - "width": 194, - "height": 65, + "width": 204, + "height": 66, "selected": false, "positionAbsolute": { - "x": 366.75, - "y": 67.5 + "x": 373.22324218750003, + "y": 66.96056315104161 + }, + "dragging": false + }, + { + "id": "toolAgentflow_1", + "position": { + "x": 177.461181640625, + "y": 108.73382161458332 + }, + "data": { + "id": "toolAgentflow_1", + "label": "Post to Teams", + "version": 1.1, + "name": "toolAgentflow", + "type": "Tool", + "color": "#d4a373", + "baseClasses": ["Tool"], + "category": "Agent Flows", + "description": "Tools allow LLM to interact with external systems", + "inputParams": [ + { + "label": "Tool", + "name": "toolAgentflowSelectedTool", + "type": "asyncOptions", + "loadMethod": "listTools", + "loadConfig": true, + "id": "toolAgentflow_1-input-toolAgentflowSelectedTool-asyncOptions", + "display": true + }, + { + "label": "Tool Input Arguments", + "name": "toolInputArgs", + "type": "array", + "acceptVariable": true, + "refresh": true, + "array": [ + { + "label": "Input Argument Name", + "name": "inputArgName", + "type": "asyncOptions", + "loadMethod": "listToolInputArgs", + "refresh": true + }, + { + "label": "Input Argument Value", + "name": "inputArgValue", + "type": "string", + "acceptVariable": true + } + ], + "show": { + "toolAgentflowSelectedTool": ".+" + }, + "id": "toolAgentflow_1-input-toolInputArgs-array", + "display": true + }, + { + "label": "Update Flow State", + "name": "toolUpdateState", + "description": "Update runtime state during the execution of the workflow", + "type": "array", + "optional": true, + "acceptVariable": true, + "array": [ + { + "label": "Key", + "name": "key", + "type": "asyncOptions", + "loadMethod": "listRuntimeStateKeys", + "freeSolo": true + }, + { + "label": "Value", + "name": "value", + "type": "string", + "acceptVariable": true, + "acceptNodeOutputAsVariable": true + } + ], + "id": "toolAgentflow_1-input-toolUpdateState-array", + "display": true + } + ], + "inputAnchors": [], + "inputs": { + "toolAgentflowSelectedTool": "microsoftTeams", + "toolInputArgs": [ + { + "inputArgName": "teamId", + "inputArgValue": "

<your-team-id>

" + }, + { + "inputArgName": "chatChannelId", + "inputArgValue": "

<your-channel-id>

" + }, + { + "inputArgName": "messageBody", + "inputArgValue": "

{{ llmAgentflow_0 }}

" + } + ], + "toolUpdateState": "", + "toolAgentflowSelectedToolConfig": { + "credential": "", + "teamsType": "chatMessage", + "chatMessageActions": "[\"sendMessage\"]", + "toolAgentflowSelectedTool": "microsoftTeams", + "chatChannelIdSendMessage": "ABCDEFG" + } + }, + "outputAnchors": [ + { + "id": "toolAgentflow_1-output-toolAgentflow", + "label": "Tool", + "name": "toolAgentflow" + } + ], + "outputs": {}, + "selected": false + }, + "type": "agentFlow", + "width": 163, + "height": 68, + "selected": false, + "positionAbsolute": { + "x": 177.461181640625, + "y": 108.73382161458332 }, "dragging": false } @@ -722,6 +848,32 @@ }, "type": "agentFlow", "id": "toolAgentflow_0-toolAgentflow_0-output-toolAgentflow-directReplyAgentflow_0-directReplyAgentflow_0" + }, + { + "source": "llmAgentflow_0", + "sourceHandle": "llmAgentflow_0-output-llmAgentflow", + "target": "toolAgentflow_1", + "targetHandle": "toolAgentflow_1", + "data": { + "sourceColor": "#64B5F6", + "targetColor": "#d4a373", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "llmAgentflow_0-llmAgentflow_0-output-llmAgentflow-toolAgentflow_1-toolAgentflow_1" + }, + { + "source": "toolAgentflow_1", + "sourceHandle": "toolAgentflow_1-output-toolAgentflow", + "target": "directReplyAgentflow_0", + "targetHandle": "directReplyAgentflow_0", + "data": { + "sourceColor": "#d4a373", + "targetColor": "#4DDBBB", + "isHumanInput": false + }, + "type": "agentFlow", + "id": "toolAgentflow_1-toolAgentflow_1-output-toolAgentflow-directReplyAgentflow_0-directReplyAgentflow_0" } ] } diff --git a/packages/server/marketplaces/chatflows/Antonym.json b/packages/server/marketplaces/chatflows/Antonym.json deleted file mode 100644 index d32b40dc..00000000 --- a/packages/server/marketplaces/chatflows/Antonym.json +++ /dev/null @@ -1,533 +0,0 @@ -{ - "description": "Output antonym of given user input using few-shot prompt template built with examples", - "framework": ["Langchain"], - "usecases": ["Basic"], - "nodes": [ - { - "width": 300, - "height": 956, - "id": "fewShotPromptTemplate_1", - "position": { - "x": 886.3229032369354, - "y": -32.18537399495787 - }, - "type": "customNode", - "data": { - "id": "fewShotPromptTemplate_1", - "label": "Few Shot Prompt Template", - "version": 1, - "name": "fewShotPromptTemplate", - "type": "FewShotPromptTemplate", - "baseClasses": ["FewShotPromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Prompt template you can build with examples", - "inputParams": [ - { - "label": "Examples", - "name": "examples", - "type": "string", - "rows": 4, - "placeholder": "[\n { \"word\": \"happy\", \"antonym\": \"sad\" },\n { \"word\": \"tall\", \"antonym\": \"short\" },\n]", - "id": "fewShotPromptTemplate_1-input-examples-string" - }, - { - "label": "Prefix", - "name": "prefix", - "type": "string", - "rows": 4, - "placeholder": "Give the antonym of every input", - "id": "fewShotPromptTemplate_1-input-prefix-string" - }, - { - "label": "Suffix", - "name": "suffix", - "type": "string", - "rows": 4, - "placeholder": "Word: {input}\nAntonym:", - "id": "fewShotPromptTemplate_1-input-suffix-string" - }, - { - "label": "Example Separator", - "name": "exampleSeparator", - "type": "string", - "placeholder": "\n\n", - "id": "fewShotPromptTemplate_1-input-exampleSeparator-string" - }, - { - "label": "Template Format", - "name": "templateFormat", - "type": "options", - "options": [ - { - "label": "f-string", - "name": "f-string" - }, - { - "label": "jinja-2", - "name": "jinja-2" - } - ], - "default": "f-string", - "id": "fewShotPromptTemplate_1-input-templateFormat-options" - } - ], - "inputAnchors": [ - { - "label": "Example Prompt", - "name": "examplePrompt", - "type": "PromptTemplate", - "id": "fewShotPromptTemplate_1-input-examplePrompt-PromptTemplate" - } - ], - "inputs": { - "examples": "[\n { \"word\": \"happy\", \"antonym\": \"sad\" },\n { \"word\": \"tall\", \"antonym\": \"short\" }\n]", - "examplePrompt": "{{promptTemplate_0.data.instance}}", - "prefix": "Give the antonym of every input", - "suffix": "Word: {input}\\nAntonym:", - "exampleSeparator": "\\n\\n", - "templateFormat": "f-string" - }, - "outputAnchors": [ - { - "id": "fewShotPromptTemplate_1-output-fewShotPromptTemplate-FewShotPromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "name": "fewShotPromptTemplate", - "label": "FewShotPromptTemplate", - "type": "FewShotPromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 886.3229032369354, - "y": -32.18537399495787 - }, - "dragging": false - }, - { - "width": 300, - "height": 513, - "id": "promptTemplate_0", - "position": { - "x": 540.0140796251119, - "y": -33.31673494170347 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_0", - "label": "Prompt Template", - "version": 1, - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_0-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_0-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "template": "Word: {word}\\nAntonym: {antonym}\\n", - "promptValues": "" - }, - "outputAnchors": [ - { - "id": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 540.0140796251119, - "y": -33.31673494170347 - }, - "dragging": false - }, - { - "width": 300, - "height": 508, - "id": "llmChain_0", - "position": { - "x": 1609.3428158423485, - "y": 409.3763727612179 - }, - "type": "customNode", - "data": { - "id": "llmChain_0", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_0-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_0-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_0-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_0-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatOpenAI_0.data.instance}}", - "prompt": "{{fewShotPromptTemplate_1.data.instance}}", - "outputParser": "", - "chainName": "", - "inputModeration": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_0-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_0-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "llmChain" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1609.3428158423485, - "y": 409.3763727612179 - }, - "dragging": false - }, - { - "id": "chatOpenAI_0", - "position": { - "x": 1220.4459070421062, - "y": -80.75004891987845 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_0", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_0-input-modelName-asyncOptions" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_0-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_0-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_0-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo", - "temperature": 0.9, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": "", - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 670, - "selected": false, - "positionAbsolute": { - "x": 1220.4459070421062, - "y": -80.75004891987845 - }, - "dragging": false - }, - { - "id": "stickyNote_0", - "position": { - "x": 1607.723380325684, - "y": 245.15558433515412 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_0", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_0-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Using few shot examples, we let LLM learns from the examples.\n\nThis template showcase how we can let LLM gives output as an antonym for given input" - }, - "outputAnchors": [ - { - "id": "stickyNote_0-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 143, - "selected": false, - "positionAbsolute": { - "x": 1607.723380325684, - "y": 245.15558433515412 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "promptTemplate_0", - "sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "target": "fewShotPromptTemplate_1", - "targetHandle": "fewShotPromptTemplate_1-input-examplePrompt-PromptTemplate", - "type": "buttonedge", - "id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-fewShotPromptTemplate_1-fewShotPromptTemplate_1-input-examplePrompt-PromptTemplate", - "data": { - "label": "" - } - }, - { - "source": "fewShotPromptTemplate_1", - "sourceHandle": "fewShotPromptTemplate_1-output-fewShotPromptTemplate-FewShotPromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "fewShotPromptTemplate_1-fewShotPromptTemplate_1-output-fewShotPromptTemplate-FewShotPromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_0-llmChain_0-input-prompt-BasePromptTemplate", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_0", - "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-llmChain_0-llmChain_0-input-model-BaseLanguageModel" - } - ] -} diff --git a/packages/server/marketplaces/chatflows/Context Chat Engine.json b/packages/server/marketplaces/chatflows/Context Chat Engine.json index 90f64eb4..e87cd650 100644 --- a/packages/server/marketplaces/chatflows/Context Chat Engine.json +++ b/packages/server/marketplaces/chatflows/Context Chat Engine.json @@ -1,7 +1,6 @@ { "description": "Answer question based on retrieved documents (context) while remembering previous conversations", "framework": ["LlamaIndex"], - "badge": "POPULAR", "usecases": ["Documents QnA"], "nodes": [ { diff --git a/packages/server/marketplaces/chatflows/Conversation Chain.json b/packages/server/marketplaces/chatflows/Conversation Chain.json index 0e57174b..c28d615d 100644 --- a/packages/server/marketplaces/chatflows/Conversation Chain.json +++ b/packages/server/marketplaces/chatflows/Conversation Chain.json @@ -1,8 +1,7 @@ { "description": "Basic example of Conversation Chain with built-in memory - works exactly like ChatGPT", - "usecases": ["Chatbot"], + "usecases": ["Basic"], "framework": ["Langchain"], - "badge": "POPULAR", "nodes": [ { "width": 300, diff --git a/packages/server/marketplaces/chatflows/Conversational Retrieval QA Chain.json b/packages/server/marketplaces/chatflows/Conversational Retrieval QA Chain.json index dbdb5cb6..6e6a3ebb 100644 --- a/packages/server/marketplaces/chatflows/Conversational Retrieval QA Chain.json +++ b/packages/server/marketplaces/chatflows/Conversational Retrieval QA Chain.json @@ -1,6 +1,5 @@ { "description": "Documents QnA using Retrieval Augmented Generation (RAG) with Mistral and FAISS for similarity search", - "badge": "POPULAR", "usecases": ["Documents QnA"], "framework": ["Langchain"], "nodes": [ diff --git a/packages/server/marketplaces/chatflows/Flowise Docs QnA.json b/packages/server/marketplaces/chatflows/Github Docs QnA.json similarity index 99% rename from packages/server/marketplaces/chatflows/Flowise Docs QnA.json rename to packages/server/marketplaces/chatflows/Github Docs QnA.json index 0d0c87dd..21e78120 100644 --- a/packages/server/marketplaces/chatflows/Flowise Docs QnA.json +++ b/packages/server/marketplaces/chatflows/Github Docs QnA.json @@ -1,6 +1,5 @@ { - "description": "Flowise Docs Github QnA using Retrieval Augmented Generation (RAG)", - "badge": "POPULAR", + "description": "Github Docs QnA using Retrieval Augmented Generation (RAG)", "usecases": ["Documents QnA"], "framework": ["Langchain"], "nodes": [ diff --git a/packages/server/marketplaces/chatflows/IfElse.json b/packages/server/marketplaces/chatflows/IfElse.json deleted file mode 100644 index ff163da2..00000000 --- a/packages/server/marketplaces/chatflows/IfElse.json +++ /dev/null @@ -1,1246 +0,0 @@ -{ - "description": "Split flows based on if else condition", - "framework": ["Langchain"], - "usecases": ["Basic"], - "nodes": [ - { - "width": 300, - "height": 513, - "id": "promptTemplate_0", - "position": { - "x": 792.9464838535649, - "y": 527.1718536712464 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_0", - "label": "Prompt Template", - "version": 1, - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_0-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_0-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "template": "You are an AI who performs one task based on the following objective: {objective}.\nRespond with how you would complete this task:", - "promptValues": "{\"objective\":\"{{question}}\"}" - }, - "outputAnchors": [ - { - "id": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 792.9464838535649, - "y": 527.1718536712464 - }, - "dragging": false - }, - { - "width": 300, - "height": 513, - "id": "promptTemplate_1", - "position": { - "x": 1995.1328578238122, - "y": -14.648035759690174 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_1", - "label": "Prompt Template", - "version": 1, - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_1-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_1-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "template": "You are a task creation AI that uses the result of an execution agent to create new tasks with the following objective: {objective}.\nThe last completed task has the result: {result}.\nBased on the result, create new tasks to be completed by the AI system that do not overlap with result.\nReturn the tasks as an array.", - "promptValues": "{\"objective\":\"{{question}}\",\"result\":\"{{ifElseFunction_0.data.instance}}\"}" - }, - "outputAnchors": [ - { - "id": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "positionAbsolute": { - "x": 1995.1328578238122, - "y": -14.648035759690174 - }, - "selected": false, - "dragging": false - }, - { - "width": 300, - "height": 508, - "id": "llmChain_0", - "position": { - "x": 1183.0899727188096, - "y": 385.0159960992951 - }, - "type": "customNode", - "data": { - "id": "llmChain_0", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_0-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_0-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_0-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_0-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatOpenAI_2.data.instance}}", - "prompt": "{{promptTemplate_0.data.instance}}", - "outputParser": "", - "chainName": "FirstChain", - "inputModeration": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_0-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_0-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "outputPrediction" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1183.0899727188096, - "y": 385.0159960992951 - }, - "dragging": false - }, - { - "width": 300, - "height": 508, - "id": "llmChain_1", - "position": { - "x": 2773.675809586143, - "y": 114.39482869328754 - }, - "type": "customNode", - "data": { - "id": "llmChain_1", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_1-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_1-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_1-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_1-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_1-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatOpenAI_1.data.instance}}", - "prompt": "{{promptTemplate_1.data.instance}}", - "outputParser": "", - "chainName": "SuccessChain", - "inputModeration": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_1-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_1-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "llmChain" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 2773.675809586143, - "y": 114.39482869328754 - }, - "dragging": false - }, - { - "width": 300, - "height": 513, - "id": "promptTemplate_2", - "position": { - "x": 1992.5456174373144, - "y": 675.5277193898106 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_2", - "label": "Prompt Template", - "version": 1, - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_2-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_2-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "template": "Politely say \"I'm not able to answer the query\"", - "promptValues": "{\"objective\":\"{{question}}\",\"result\":\"\"}" - }, - "outputAnchors": [ - { - "id": "promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "positionAbsolute": { - "x": 1992.5456174373144, - "y": 675.5277193898106 - }, - "selected": false, - "dragging": false - }, - { - "width": 300, - "height": 508, - "id": "llmChain_2", - "position": { - "x": 2800.114465373451, - "y": 909.2318348964463 - }, - "type": "customNode", - "data": { - "id": "llmChain_2", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_2-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_2-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_2-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_2-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_2-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatAnthropic_0.data.instance}}", - "prompt": "{{promptTemplate_2.data.instance}}", - "outputParser": "", - "chainName": "FallbackChain", - "inputModeration": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_2-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_2-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "llmChain" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 2800.114465373451, - "y": 909.2318348964463 - }, - "dragging": false - }, - { - "width": 300, - "height": 757, - "id": "ifElseFunction_0", - "position": { - "x": 1590.6560099561739, - "y": 265.36655719326177 - }, - "type": "customNode", - "data": { - "id": "ifElseFunction_0", - "label": "IfElse Function", - "version": 2, - "name": "ifElseFunction", - "type": "IfElseFunction", - "baseClasses": ["IfElseFunction", "Utilities"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Split flows based on If Else javascript functions", - "inputParams": [ - { - "label": "Input Variables", - "name": "functionInputVariables", - "description": "Input variables can be used in the function with prefix $. For example: $var", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "ifElseFunction_0-input-functionInputVariables-json" - }, - { - "label": "IfElse Name", - "name": "functionName", - "type": "string", - "optional": true, - "placeholder": "If Condition Match", - "id": "ifElseFunction_0-input-functionName-string" - }, - { - "label": "If Function", - "name": "ifFunction", - "description": "Function must return a value", - "type": "code", - "rows": 2, - "default": "if (\"hello\" == \"hello\") {\n return true;\n}", - "id": "ifElseFunction_0-input-ifFunction-code" - }, - { - "label": "Else Function", - "name": "elseFunction", - "description": "Function must return a value", - "type": "code", - "rows": 2, - "default": "return false;", - "id": "ifElseFunction_0-input-elseFunction-code" - } - ], - "inputAnchors": [], - "inputs": { - "functionInputVariables": "{\"task\":\"{{llmChain_0.data.instance}}\"}", - "functionName": "If Condition Match", - "ifFunction": "if ($task.includes(\"task\")) {\n // return $task to be used in next prompt as variable\n return $task;\n}", - "elseFunction": "return false;" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "description": "", - "options": [ - { - "id": "ifElseFunction_0-output-returnTrue-string|number|boolean|json|array", - "name": "returnTrue", - "label": "True", - "description": "", - "type": "string | number | boolean | json | array" - }, - { - "id": "ifElseFunction_0-output-returnFalse-string|number|boolean|json|array", - "name": "returnFalse", - "label": "False", - "description": "", - "type": "string | number | boolean | json | array" - } - ], - "default": "returnTrue" - } - ], - "outputs": { - "output": "returnTrue" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1590.6560099561739, - "y": 265.36655719326177 - }, - "dragging": false - }, - { - "width": 300, - "height": 670, - "id": "chatOpenAI_1", - "position": { - "x": 2351.7234095119156, - "y": -394.0409300837044 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_1", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_1-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_1-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_1-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_1-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_1-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_1-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo", - "temperature": 0.9, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 2351.7234095119156, - "y": -394.0409300837044 - }, - "dragging": false - }, - { - "width": 300, - "height": 670, - "id": "chatOpenAI_2", - "position": { - "x": 789.3453885560219, - "y": -179.07897273438854 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_2", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_2-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_2-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_2-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_2-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_2-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_2-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo", - "temperature": 0.9, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 789.3453885560219, - "y": -179.07897273438854 - }, - "dragging": false - }, - { - "id": "chatAnthropic_0", - "position": { - "x": 2381.220361865136, - "y": 393.26149491753074 - }, - "type": "customNode", - "data": { - "id": "chatAnthropic_0", - "label": "ChatAnthropic", - "version": 6, - "name": "chatAnthropic", - "type": "ChatAnthropic", - "baseClasses": ["ChatAnthropic", "ChatAnthropicMessages", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around ChatAnthropic large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["anthropicApi"], - "id": "chatAnthropic_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "claude-3-haiku", - "id": "chatAnthropic_0-input-modelName-asyncOptions" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatAnthropic_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokensToSample", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatAnthropic_0-input-maxTokensToSample-number" - }, - { - "label": "Top P", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatAnthropic_0-input-topP-number" - }, - { - "label": "Top K", - "name": "topK", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatAnthropic_0-input-topK-number" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses claude-3-* models when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatAnthropic_0-input-allowImageUploads-boolean" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatAnthropic_0-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "claude-3-haiku-20240307", - "temperature": 0.9, - "maxTokensToSample": "", - "topP": "", - "topK": "", - "allowImageUploads": "" - }, - "outputAnchors": [ - { - "id": "chatAnthropic_0-output-chatAnthropic-ChatAnthropic|ChatAnthropicMessages|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatAnthropic", - "label": "ChatAnthropic", - "description": "Wrapper around ChatAnthropic large language models that use the Chat endpoint", - "type": "ChatAnthropic | ChatAnthropicMessages | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 670, - "selected": false, - "dragging": false, - "positionAbsolute": { - "x": 2381.220361865136, - "y": 393.26149491753074 - } - }, - { - "id": "stickyNote_0", - "position": { - "x": 1585.520839473698, - "y": 51.83677692300674 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_0", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_0-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Split the path into 2 ways according to condition\n\n1. If response from first LLM Chain contains the word \"task\", carry on with the next prompt\n\n2. Otherwise, politely reject user's request" - }, - "outputAnchors": [ - { - "id": "stickyNote_0-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 183, - "selected": false, - "positionAbsolute": { - "x": 1585.520839473698, - "y": 51.83677692300674 - }, - "dragging": false - }, - { - "id": "stickyNote_1", - "position": { - "x": 2791.378655166414, - "y": 699.1817665106969 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_1", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_1-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Example question:\n\n- Solve world hunger" - }, - "outputAnchors": [ - { - "id": "stickyNote_1-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 82, - "selected": false, - "positionAbsolute": { - "x": 2791.378655166414, - "y": 699.1817665106969 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "promptTemplate_0", - "sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_0-llmChain_0-input-prompt-BasePromptTemplate", - "data": { - "label": "" - } - }, - { - "source": "promptTemplate_1", - "sourceHandle": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "target": "llmChain_1", - "targetHandle": "llmChain_1-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "promptTemplate_1-promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate", - "data": { - "label": "" - } - }, - { - "source": "promptTemplate_2", - "sourceHandle": "promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate", - "target": "llmChain_2", - "targetHandle": "llmChain_2-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "promptTemplate_2-promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate-llmChain_2-llmChain_2-input-prompt-BasePromptTemplate" - }, - { - "source": "llmChain_0", - "sourceHandle": "llmChain_0-output-outputPrediction-string|json", - "target": "ifElseFunction_0", - "targetHandle": "ifElseFunction_0-input-functionInputVariables-json", - "type": "buttonedge", - "id": "llmChain_0-llmChain_0-output-outputPrediction-string|json-ifElseFunction_0-ifElseFunction_0-input-functionInputVariables-json" - }, - { - "source": "ifElseFunction_0", - "sourceHandle": "ifElseFunction_0-output-returnFalse-string|number|boolean|json|array", - "target": "promptTemplate_2", - "targetHandle": "promptTemplate_2-input-promptValues-json", - "type": "buttonedge", - "id": "ifElseFunction_0-ifElseFunction_0-output-returnFalse-string|number|boolean|json|array-promptTemplate_2-promptTemplate_2-input-promptValues-json" - }, - { - "source": "ifElseFunction_0", - "sourceHandle": "ifElseFunction_0-output-returnTrue-string|number|boolean|json|array", - "target": "promptTemplate_1", - "targetHandle": "promptTemplate_1-input-promptValues-json", - "type": "buttonedge", - "id": "ifElseFunction_0-ifElseFunction_0-output-returnTrue-string|number|boolean|json|array-promptTemplate_1-promptTemplate_1-input-promptValues-json" - }, - { - "source": "chatOpenAI_1", - "sourceHandle": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "llmChain_1", - "targetHandle": "llmChain_1-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_1-chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-llmChain_1-llmChain_1-input-model-BaseLanguageModel" - }, - { - "source": "chatOpenAI_2", - "sourceHandle": "chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_2-chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-llmChain_0-llmChain_0-input-model-BaseLanguageModel" - }, - { - "source": "chatAnthropic_0", - "sourceHandle": "chatAnthropic_0-output-chatAnthropic-ChatAnthropic|ChatAnthropicMessages|BaseChatModel|BaseLanguageModel|Runnable", - "target": "llmChain_2", - "targetHandle": "llmChain_2-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatAnthropic_0-chatAnthropic_0-output-chatAnthropic-ChatAnthropic|ChatAnthropicMessages|BaseChatModel|BaseLanguageModel|Runnable-llmChain_2-llmChain_2-input-model-BaseLanguageModel" - } - ] -} diff --git a/packages/server/marketplaces/chatflows/Local QnA.json b/packages/server/marketplaces/chatflows/Local QnA.json index 063a0eb0..86f2e488 100644 --- a/packages/server/marketplaces/chatflows/Local QnA.json +++ b/packages/server/marketplaces/chatflows/Local QnA.json @@ -1,6 +1,5 @@ { "description": "QnA chain using Ollama local LLM, LocalAI embedding model, and Faiss local vector store", - "badge": "POPULAR", "usecases": ["Documents QnA"], "framework": ["Langchain"], "nodes": [ diff --git a/packages/server/marketplaces/chatflows/Multi Prompt Chain.json b/packages/server/marketplaces/chatflows/Multi Prompt Chain.json deleted file mode 100644 index 4cdbda16..00000000 --- a/packages/server/marketplaces/chatflows/Multi Prompt Chain.json +++ /dev/null @@ -1,499 +0,0 @@ -{ - "description": "A chain that automatically picks an appropriate prompt from multiple prompts", - "usecases": ["Basic"], - "framework": ["Langchain"], - "nodes": [ - { - "width": 300, - "height": 632, - "id": "promptRetriever_0", - "position": { - "x": 197.46642699727397, - "y": 25.945621297410923 - }, - "type": "customNode", - "data": { - "id": "promptRetriever_0", - "label": "Prompt Retriever", - "name": "promptRetriever", - "version": 1, - "type": "PromptRetriever", - "baseClasses": ["PromptRetriever"], - "category": "Retrievers", - "description": "Store prompt template with name & description to be later queried by MultiPromptChain", - "inputParams": [ - { - "label": "Prompt Name", - "name": "name", - "type": "string", - "placeholder": "physics-qa", - "id": "promptRetriever_0-input-name-string" - }, - { - "label": "Prompt Description", - "name": "description", - "type": "string", - "rows": 3, - "description": "Description of what the prompt does and when it should be used", - "placeholder": "Good for answering questions about physics", - "id": "promptRetriever_0-input-description-string" - }, - { - "label": "Prompt System Message", - "name": "systemMessage", - "type": "string", - "rows": 4, - "placeholder": "You are a very smart physics professor. You are great at answering questions about physics in a concise and easy to understand manner. When you don't know the answer to a question you admit that you don't know.", - "id": "promptRetriever_0-input-systemMessage-string" - } - ], - "inputAnchors": [], - "inputs": { - "name": "physics", - "description": "Good for answering questions about physics", - "systemMessage": "You are a very smart physics professor. You are great at answering questions about physics in a concise and easy to understand manner. When you don't know the answer to a question you admit that you don't know." - }, - "outputAnchors": [ - { - "id": "promptRetriever_0-output-promptRetriever-PromptRetriever", - "name": "promptRetriever", - "label": "PromptRetriever", - "type": "PromptRetriever" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 197.46642699727397, - "y": 25.945621297410923 - }, - "dragging": false - }, - { - "width": 300, - "height": 280, - "id": "multiPromptChain_0", - "position": { - "x": 1619.1305522575494, - "y": 210.28103293821243 - }, - "type": "customNode", - "data": { - "id": "multiPromptChain_0", - "label": "Multi Prompt Chain", - "name": "multiPromptChain", - "version": 2, - "type": "MultiPromptChain", - "baseClasses": ["MultiPromptChain", "MultiRouteChain", "BaseChain", "BaseLangChain"], - "category": "Chains", - "description": "Chain automatically picks an appropriate prompt from multiple prompt templates", - "inputParams": [], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "multiPromptChain_0-input-model-BaseLanguageModel" - }, - { - "label": "Prompt Retriever", - "name": "promptRetriever", - "type": "PromptRetriever", - "list": true, - "id": "multiPromptChain_0-input-promptRetriever-PromptRetriever" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "multiPromptChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "inputModeration": "", - "model": "{{chatOpenAI_0.data.instance}}", - "promptRetriever": [ - "{{promptRetriever_0.data.instance}}", - "{{promptRetriever_2.data.instance}}", - "{{promptRetriever_1.data.instance}}" - ] - }, - "outputAnchors": [ - { - "id": "multiPromptChain_0-output-multiPromptChain-MultiPromptChain|MultiRouteChain|BaseChain|BaseLangChain", - "name": "multiPromptChain", - "label": "MultiPromptChain", - "type": "MultiPromptChain | MultiRouteChain | BaseChain | BaseLangChain" - } - ], - "outputs": {}, - "selected": false - }, - "positionAbsolute": { - "x": 1619.1305522575494, - "y": 210.28103293821243 - }, - "selected": false, - "dragging": false - }, - { - "width": 300, - "height": 632, - "id": "promptRetriever_1", - "position": { - "x": 539.1322780233141, - "y": -250.72967142925938 - }, - "type": "customNode", - "data": { - "id": "promptRetriever_1", - "label": "Prompt Retriever", - "name": "promptRetriever", - "version": 1, - "type": "PromptRetriever", - "baseClasses": ["PromptRetriever"], - "category": "Retrievers", - "description": "Store prompt template with name & description to be later queried by MultiPromptChain", - "inputParams": [ - { - "label": "Prompt Name", - "name": "name", - "type": "string", - "placeholder": "physics-qa", - "id": "promptRetriever_1-input-name-string" - }, - { - "label": "Prompt Description", - "name": "description", - "type": "string", - "rows": 3, - "description": "Description of what the prompt does and when it should be used", - "placeholder": "Good for answering questions about physics", - "id": "promptRetriever_1-input-description-string" - }, - { - "label": "Prompt System Message", - "name": "systemMessage", - "type": "string", - "rows": 4, - "placeholder": "You are a very smart physics professor. You are great at answering questions about physics in a concise and easy to understand manner. When you don't know the answer to a question you admit that you don't know.", - "id": "promptRetriever_1-input-systemMessage-string" - } - ], - "inputAnchors": [], - "inputs": { - "name": "math", - "description": "Good for answering math questions", - "systemMessage": "You are a very good mathematician. You are great at answering math questions. You are so good because you are able to break down hard problems into their component parts, answer the component parts, and then put them together to answer the broader question." - }, - "outputAnchors": [ - { - "id": "promptRetriever_1-output-promptRetriever-PromptRetriever", - "name": "promptRetriever", - "label": "PromptRetriever", - "type": "PromptRetriever" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 539.1322780233141, - "y": -250.72967142925938 - }, - "dragging": false - }, - { - "width": 300, - "height": 632, - "id": "promptRetriever_2", - "position": { - "x": 872.6184534864304, - "y": -366.9443140594265 - }, - "type": "customNode", - "data": { - "id": "promptRetriever_2", - "label": "Prompt Retriever", - "name": "promptRetriever", - "version": 1, - "type": "PromptRetriever", - "baseClasses": ["PromptRetriever"], - "category": "Retrievers", - "description": "Store prompt template with name & description to be later queried by MultiPromptChain", - "inputParams": [ - { - "label": "Prompt Name", - "name": "name", - "type": "string", - "placeholder": "physics-qa", - "id": "promptRetriever_2-input-name-string" - }, - { - "label": "Prompt Description", - "name": "description", - "type": "string", - "rows": 3, - "description": "Description of what the prompt does and when it should be used", - "placeholder": "Good for answering questions about physics", - "id": "promptRetriever_2-input-description-string" - }, - { - "label": "Prompt System Message", - "name": "systemMessage", - "type": "string", - "rows": 4, - "placeholder": "You are a very smart physics professor. You are great at answering questions about physics in a concise and easy to understand manner. When you don't know the answer to a question you admit that you don't know.", - "id": "promptRetriever_2-input-systemMessage-string" - } - ], - "inputAnchors": [], - "inputs": { - "name": "history", - "description": "Good for answering questions about history", - "systemMessage": "You are a very smart history professor. You are great at answering questions about history in a concise and easy to understand manner. When you don't know the answer to a question you admit that you don't know." - }, - "outputAnchors": [ - { - "id": "promptRetriever_2-output-promptRetriever-PromptRetriever", - "name": "promptRetriever", - "label": "PromptRetriever", - "type": "PromptRetriever" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 872.6184534864304, - "y": -366.9443140594265 - }, - "dragging": false - }, - { - "width": 300, - "height": 523, - "id": "chatOpenAI_0", - "position": { - "x": 1228.4059611466973, - "y": -326.46419383157513 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_0", - "label": "ChatOpenAI", - "name": "chatOpenAI", - "version": 6.0, - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_0-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "default": 0.9, - "optional": true, - "id": "chatOpenAI_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_0-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_0-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_0-input-cache-BaseCache" - } - ], - "inputs": { - "modelName": "gpt-3.5-turbo", - "temperature": 0.9, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1228.4059611466973, - "y": -326.46419383157513 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "promptRetriever_0", - "sourceHandle": "promptRetriever_0-output-promptRetriever-PromptRetriever", - "target": "multiPromptChain_0", - "targetHandle": "multiPromptChain_0-input-promptRetriever-PromptRetriever", - "type": "buttonedge", - "id": "promptRetriever_0-promptRetriever_0-output-promptRetriever-PromptRetriever-multiPromptChain_0-multiPromptChain_0-input-promptRetriever-PromptRetriever", - "data": { - "label": "" - } - }, - { - "source": "promptRetriever_2", - "sourceHandle": "promptRetriever_2-output-promptRetriever-PromptRetriever", - "target": "multiPromptChain_0", - "targetHandle": "multiPromptChain_0-input-promptRetriever-PromptRetriever", - "type": "buttonedge", - "id": "promptRetriever_2-promptRetriever_2-output-promptRetriever-PromptRetriever-multiPromptChain_0-multiPromptChain_0-input-promptRetriever-PromptRetriever", - "data": { - "label": "" - } - }, - { - "source": "promptRetriever_1", - "sourceHandle": "promptRetriever_1-output-promptRetriever-PromptRetriever", - "target": "multiPromptChain_0", - "targetHandle": "multiPromptChain_0-input-promptRetriever-PromptRetriever", - "type": "buttonedge", - "id": "promptRetriever_1-promptRetriever_1-output-promptRetriever-PromptRetriever-multiPromptChain_0-multiPromptChain_0-input-promptRetriever-PromptRetriever", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_0", - "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel", - "target": "multiPromptChain_0", - "targetHandle": "multiPromptChain_0-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-multiPromptChain_0-multiPromptChain_0-input-model-BaseLanguageModel", - "data": { - "label": "" - } - } - ] -} diff --git a/packages/server/marketplaces/chatflows/Multi Retrieval QA Chain.json b/packages/server/marketplaces/chatflows/Multi Retrieval QA Chain.json deleted file mode 100644 index 298db5ab..00000000 --- a/packages/server/marketplaces/chatflows/Multi Retrieval QA Chain.json +++ /dev/null @@ -1,1222 +0,0 @@ -{ - "description": "A chain that automatically picks an appropriate vector store retriever from multiple different vector databases", - "usecases": ["Documents QnA"], - "framework": ["Langchain"], - "nodes": [ - { - "width": 300, - "height": 506, - "id": "vectorStoreRetriever_0", - "position": { - "x": 712.9322670298264, - "y": 860.5462810572917 - }, - "type": "customNode", - "data": { - "id": "vectorStoreRetriever_0", - "label": "Vector Store Retriever", - "version": 1, - "name": "vectorStoreRetriever", - "type": "VectorStoreRetriever", - "baseClasses": ["VectorStoreRetriever"], - "category": "Retrievers", - "description": "Store vector store as retriever. Used with MultiRetrievalQAChain", - "inputParams": [ - { - "label": "Retriever Name", - "name": "name", - "type": "string", - "placeholder": "netflix movies", - "id": "vectorStoreRetriever_0-input-name-string" - }, - { - "label": "Retriever Description", - "name": "description", - "type": "string", - "rows": 3, - "description": "Description of when to use the vector store retriever", - "placeholder": "Good for answering questions about netflix movies", - "id": "vectorStoreRetriever_0-input-description-string" - } - ], - "inputAnchors": [ - { - "label": "Vector Store", - "name": "vectorStore", - "type": "VectorStore", - "id": "vectorStoreRetriever_0-input-vectorStore-VectorStore" - } - ], - "inputs": { - "vectorStore": "{{supabase_0.data.instance}}", - "name": "aqua teen", - "description": "Good for answering questions about Aqua Teen Hunger Force theme song" - }, - "outputAnchors": [ - { - "id": "vectorStoreRetriever_0-output-vectorStoreRetriever-VectorStoreRetriever", - "name": "vectorStoreRetriever", - "label": "VectorStoreRetriever", - "type": "VectorStoreRetriever" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 712.9322670298264, - "y": 860.5462810572917 - }, - "dragging": false - }, - { - "width": 300, - "height": 429, - "id": "multiRetrievalQAChain_0", - "position": { - "x": 1563.0150452201099, - "y": 460.78375893303934 - }, - "type": "customNode", - "data": { - "id": "multiRetrievalQAChain_0", - "label": "Multi Retrieval QA Chain", - "version": 2, - "name": "multiRetrievalQAChain", - "type": "MultiRetrievalQAChain", - "baseClasses": ["MultiRetrievalQAChain", "MultiRouteChain", "BaseChain", "BaseLangChain"], - "category": "Chains", - "description": "QA Chain that automatically picks an appropriate vector store from multiple retrievers", - "inputParams": [ - { - "label": "Return Source Documents", - "name": "returnSourceDocuments", - "type": "boolean", - "optional": true - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "multiRetrievalQAChain_0-input-model-BaseLanguageModel" - }, - { - "label": "Vector Store Retriever", - "name": "vectorStoreRetriever", - "type": "VectorStoreRetriever", - "list": true, - "id": "multiRetrievalQAChain_0-input-vectorStoreRetriever-VectorStoreRetriever" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "multiRetrievalQAChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "inputModeration": "", - "model": "{{chatOpenAI_0.data.instance}}", - "vectorStoreRetriever": [ - "{{vectorStoreRetriever_0.data.instance}}", - "{{vectorStoreRetriever_1.data.instance}}", - "{{vectorStoreRetriever_2.data.instance}}" - ] - }, - "outputAnchors": [ - { - "id": "multiRetrievalQAChain_0-output-multiRetrievalQAChain-MultiRetrievalQAChain|MultiRouteChain|BaseChain|BaseLangChain", - "name": "multiRetrievalQAChain", - "label": "MultiRetrievalQAChain", - "type": "MultiRetrievalQAChain | MultiRouteChain | BaseChain | BaseLangChain" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1563.0150452201099, - "y": 460.78375893303934 - }, - "dragging": false - }, - { - "width": 300, - "height": 506, - "id": "vectorStoreRetriever_1", - "position": { - "x": 711.4902931206071, - "y": 315.2414600651632 - }, - "type": "customNode", - "data": { - "id": "vectorStoreRetriever_1", - "label": "Vector Store Retriever", - "version": 1, - "name": "vectorStoreRetriever", - "type": "VectorStoreRetriever", - "baseClasses": ["VectorStoreRetriever"], - "category": "Retrievers", - "description": "Store vector store as retriever. Used with MultiRetrievalQAChain", - "inputParams": [ - { - "label": "Retriever Name", - "name": "name", - "type": "string", - "placeholder": "netflix movies", - "id": "vectorStoreRetriever_1-input-name-string" - }, - { - "label": "Retriever Description", - "name": "description", - "type": "string", - "rows": 3, - "description": "Description of when to use the vector store retriever", - "placeholder": "Good for answering questions about netflix movies", - "id": "vectorStoreRetriever_1-input-description-string" - } - ], - "inputAnchors": [ - { - "label": "Vector Store", - "name": "vectorStore", - "type": "VectorStore", - "id": "vectorStoreRetriever_1-input-vectorStore-VectorStore" - } - ], - "inputs": { - "vectorStore": "{{chroma_0.data.instance}}", - "name": "mst3k", - "description": "Good for answering questions about Mystery Science Theater 3000 theme song" - }, - "outputAnchors": [ - { - "id": "vectorStoreRetriever_1-output-vectorStoreRetriever-VectorStoreRetriever", - "name": "vectorStoreRetriever", - "label": "VectorStoreRetriever", - "type": "VectorStoreRetriever" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 711.4902931206071, - "y": 315.2414600651632 - }, - "dragging": false - }, - { - "width": 300, - "height": 506, - "id": "vectorStoreRetriever_2", - "position": { - "x": 706.0716220151372, - "y": -217.51566869136752 - }, - "type": "customNode", - "data": { - "id": "vectorStoreRetriever_2", - "label": "Vector Store Retriever", - "version": 1, - "name": "vectorStoreRetriever", - "type": "VectorStoreRetriever", - "baseClasses": ["VectorStoreRetriever"], - "category": "Retrievers", - "description": "Store vector store as retriever. Used with MultiRetrievalQAChain", - "inputParams": [ - { - "label": "Retriever Name", - "name": "name", - "type": "string", - "placeholder": "netflix movies", - "id": "vectorStoreRetriever_2-input-name-string" - }, - { - "label": "Retriever Description", - "name": "description", - "type": "string", - "rows": 3, - "description": "Description of when to use the vector store retriever", - "placeholder": "Good for answering questions about netflix movies", - "id": "vectorStoreRetriever_2-input-description-string" - } - ], - "inputAnchors": [ - { - "label": "Vector Store", - "name": "vectorStore", - "type": "VectorStore", - "id": "vectorStoreRetriever_2-input-vectorStore-VectorStore" - } - ], - "inputs": { - "vectorStore": "{{pinecone_0.data.instance}}", - "name": "animaniacs", - "description": "Good for answering questions about Animaniacs theme song" - }, - "outputAnchors": [ - { - "id": "vectorStoreRetriever_2-output-vectorStoreRetriever-VectorStoreRetriever", - "name": "vectorStoreRetriever", - "label": "VectorStoreRetriever", - "type": "VectorStoreRetriever" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 706.0716220151372, - "y": -217.51566869136752 - }, - "dragging": false - }, - { - "width": 300, - "height": 424, - "id": "openAIEmbeddings_0", - "position": { - "x": -212.46977797044045, - "y": 252.45726960585722 - }, - "type": "customNode", - "data": { - "id": "openAIEmbeddings_0", - "label": "OpenAI Embeddings", - "version": 4, - "name": "openAIEmbeddings", - "type": "OpenAIEmbeddings", - "baseClasses": ["OpenAIEmbeddings", "Embeddings"], - "category": "Embeddings", - "description": "OpenAI API to generate embeddings for a given text", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "openAIEmbeddings_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "text-embedding-ada-002", - "id": "openAIEmbeddings_0-input-modelName-asyncOptions" - }, - { - "label": "Strip New Lines", - "name": "stripNewLines", - "type": "boolean", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-stripNewLines-boolean" - }, - { - "label": "Batch Size", - "name": "batchSize", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-batchSize-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-basepath-string" - }, - { - "label": "Dimensions", - "name": "dimensions", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-dimensions-number" - } - ], - "inputAnchors": [], - "inputs": { - "modelName": "text-embedding-ada-002", - "stripNewLines": "", - "batchSize": "", - "timeout": "", - "basepath": "", - "dimensions": "" - }, - "outputAnchors": [ - { - "id": "openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "name": "openAIEmbeddings", - "label": "OpenAIEmbeddings", - "description": "OpenAI API to generate embeddings for a given text", - "type": "OpenAIEmbeddings | Embeddings" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": -212.46977797044045, - "y": 252.45726960585722 - }, - "dragging": false - }, - { - "width": 300, - "height": 670, - "id": "chatOpenAI_0", - "position": { - "x": 1166.929741805626, - "y": -297.9691758089252 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_0", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_0-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_0-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_0-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_0-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo", - "temperature": 0.9, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1166.929741805626, - "y": -297.9691758089252 - }, - "dragging": false - }, - { - "width": 300, - "height": 606, - "id": "pinecone_0", - "position": { - "x": 268.04147939086755, - "y": -407.5681206851249 - }, - "type": "customNode", - "data": { - "id": "pinecone_0", - "label": "Pinecone", - "version": 3, - "name": "pinecone", - "type": "Pinecone", - "baseClasses": ["Pinecone", "VectorStoreRetriever", "BaseRetriever"], - "category": "Vector Stores", - "description": "Upsert embedded data and perform similarity or mmr search using Pinecone, a leading fully managed hosted vector database", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["pineconeApi"], - "id": "pinecone_0-input-credential-credential" - }, - { - "label": "Pinecone Index", - "name": "pineconeIndex", - "type": "string", - "id": "pinecone_0-input-pineconeIndex-string" - }, - { - "label": "Pinecone Namespace", - "name": "pineconeNamespace", - "type": "string", - "placeholder": "my-first-namespace", - "additionalParams": true, - "optional": true, - "id": "pinecone_0-input-pineconeNamespace-string" - }, - { - "label": "Pinecone Metadata Filter", - "name": "pineconeMetadataFilter", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "pinecone_0-input-pineconeMetadataFilter-json" - }, - { - "label": "Top K", - "name": "topK", - "description": "Number of top results to fetch. Default to 4", - "placeholder": "4", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "pinecone_0-input-topK-number" - }, - { - "label": "Search Type", - "name": "searchType", - "type": "options", - "default": "similarity", - "options": [ - { - "label": "Similarity", - "name": "similarity" - }, - { - "label": "Max Marginal Relevance", - "name": "mmr" - } - ], - "additionalParams": true, - "optional": true, - "id": "pinecone_0-input-searchType-options" - }, - { - "label": "Fetch K (for MMR Search)", - "name": "fetchK", - "description": "Number of initial documents to fetch for MMR reranking. Default to 20. Used only when the search type is MMR", - "placeholder": "20", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "pinecone_0-input-fetchK-number" - }, - { - "label": "Lambda (for MMR Search)", - "name": "lambda", - "description": "Number between 0 and 1 that determines the degree of diversity among the results, where 0 corresponds to maximum diversity and 1 to minimum diversity. Used only when the search type is MMR", - "placeholder": "0.5", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "pinecone_0-input-lambda-number" - } - ], - "inputAnchors": [ - { - "label": "Document", - "name": "document", - "type": "Document", - "list": true, - "optional": true, - "id": "pinecone_0-input-document-Document" - }, - { - "label": "Embeddings", - "name": "embeddings", - "type": "Embeddings", - "id": "pinecone_0-input-embeddings-Embeddings" - }, - { - "label": "Record Manager", - "name": "recordManager", - "type": "RecordManager", - "description": "Keep track of the record to prevent duplication", - "optional": true, - "id": "pinecone_0-input-recordManager-RecordManager" - } - ], - "inputs": { - "document": "", - "embeddings": "{{openAIEmbeddings_0.data.instance}}", - "recordManager": "", - "pineconeIndex": "", - "pineconeNamespace": "", - "pineconeMetadataFilter": "", - "topK": "", - "searchType": "similarity", - "fetchK": "", - "lambda": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "description": "", - "options": [ - { - "id": "pinecone_0-output-retriever-Pinecone|VectorStoreRetriever|BaseRetriever", - "name": "retriever", - "label": "Pinecone Retriever", - "description": "", - "type": "Pinecone | VectorStoreRetriever | BaseRetriever" - }, - { - "id": "pinecone_0-output-vectorStore-Pinecone|VectorStore", - "name": "vectorStore", - "label": "Pinecone Vector Store", - "description": "", - "type": "Pinecone | VectorStore" - } - ], - "default": "retriever" - } - ], - "outputs": { - "output": "vectorStore" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 268.04147939086755, - "y": -407.5681206851249 - }, - "dragging": false - }, - { - "width": 300, - "height": 704, - "id": "chroma_0", - "position": { - "x": 271.26687710753146, - "y": 240.7980496352519 - }, - "type": "customNode", - "data": { - "id": "chroma_0", - "label": "Chroma", - "version": 2, - "name": "chroma", - "type": "Chroma", - "baseClasses": ["Chroma", "VectorStoreRetriever", "BaseRetriever"], - "category": "Vector Stores", - "description": "Upsert embedded data and perform similarity search upon query using Chroma, an open-source embedding database", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "description": "Only needed if you have chroma on cloud services with X-Api-key", - "optional": true, - "credentialNames": ["chromaApi"], - "id": "chroma_0-input-credential-credential" - }, - { - "label": "Collection Name", - "name": "collectionName", - "type": "string", - "id": "chroma_0-input-collectionName-string" - }, - { - "label": "Chroma URL", - "name": "chromaURL", - "type": "string", - "optional": true, - "id": "chroma_0-input-chromaURL-string" - }, - { - "label": "Chroma Metadata Filter", - "name": "chromaMetadataFilter", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chroma_0-input-chromaMetadataFilter-json" - }, - { - "label": "Top K", - "name": "topK", - "description": "Number of top results to fetch. Default to 4", - "placeholder": "4", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "chroma_0-input-topK-number" - } - ], - "inputAnchors": [ - { - "label": "Document", - "name": "document", - "type": "Document", - "list": true, - "optional": true, - "id": "chroma_0-input-document-Document" - }, - { - "label": "Embeddings", - "name": "embeddings", - "type": "Embeddings", - "id": "chroma_0-input-embeddings-Embeddings" - }, - { - "label": "Record Manager", - "name": "recordManager", - "type": "RecordManager", - "description": "Keep track of the record to prevent duplication", - "optional": true, - "id": "chroma_0-input-recordManager-RecordManager" - } - ], - "inputs": { - "document": "", - "embeddings": "{{openAIEmbeddings_0.data.instance}}", - "recordManager": "", - "collectionName": "", - "chromaURL": "", - "chromaMetadataFilter": "", - "topK": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "description": "", - "options": [ - { - "id": "chroma_0-output-retriever-Chroma|VectorStoreRetriever|BaseRetriever", - "name": "retriever", - "label": "Chroma Retriever", - "description": "", - "type": "Chroma | VectorStoreRetriever | BaseRetriever" - }, - { - "id": "chroma_0-output-vectorStore-Chroma|VectorStore", - "name": "vectorStore", - "label": "Chroma Vector Store", - "description": "", - "type": "Chroma | VectorStore" - } - ], - "default": "retriever" - } - ], - "outputs": { - "output": "vectorStore" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 271.26687710753146, - "y": 240.7980496352519 - }, - "dragging": false - }, - { - "width": 300, - "height": 803, - "id": "supabase_0", - "position": { - "x": 274.75982285806055, - "y": 982.5186034037372 - }, - "type": "customNode", - "data": { - "id": "supabase_0", - "label": "Supabase", - "version": 4, - "name": "supabase", - "type": "Supabase", - "baseClasses": ["Supabase", "VectorStoreRetriever", "BaseRetriever"], - "category": "Vector Stores", - "description": "Upsert embedded data and perform similarity or mmr search upon query using Supabase via pgvector extension", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["supabaseApi"], - "id": "supabase_0-input-credential-credential" - }, - { - "label": "Supabase Project URL", - "name": "supabaseProjUrl", - "type": "string", - "id": "supabase_0-input-supabaseProjUrl-string" - }, - { - "label": "Table Name", - "name": "tableName", - "type": "string", - "id": "supabase_0-input-tableName-string" - }, - { - "label": "Query Name", - "name": "queryName", - "type": "string", - "id": "supabase_0-input-queryName-string" - }, - { - "label": "Supabase Metadata Filter", - "name": "supabaseMetadataFilter", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "supabase_0-input-supabaseMetadataFilter-json" - }, - { - "label": "Supabase RPC Filter", - "name": "supabaseRPCFilter", - "type": "string", - "rows": 4, - "placeholder": "filter(\"metadata->a::int\", \"gt\", 5)\n.filter(\"metadata->c::int\", \"gt\", 7)\n.filter(\"metadata->>stuff\", \"eq\", \"right\");", - "description": "Query builder-style filtering. If this is set, will override the metadata filter. Refer
here for more information", - "optional": true, - "additionalParams": true, - "id": "supabase_0-input-supabaseRPCFilter-string" - }, - { - "label": "Top K", - "name": "topK", - "description": "Number of top results to fetch. Default to 4", - "placeholder": "4", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "supabase_0-input-topK-number" - }, - { - "label": "Search Type", - "name": "searchType", - "type": "options", - "default": "similarity", - "options": [ - { - "label": "Similarity", - "name": "similarity" - }, - { - "label": "Max Marginal Relevance", - "name": "mmr" - } - ], - "additionalParams": true, - "optional": true, - "id": "supabase_0-input-searchType-options" - }, - { - "label": "Fetch K (for MMR Search)", - "name": "fetchK", - "description": "Number of initial documents to fetch for MMR reranking. Default to 20. Used only when the search type is MMR", - "placeholder": "20", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "supabase_0-input-fetchK-number" - }, - { - "label": "Lambda (for MMR Search)", - "name": "lambda", - "description": "Number between 0 and 1 that determines the degree of diversity among the results, where 0 corresponds to maximum diversity and 1 to minimum diversity. Used only when the search type is MMR", - "placeholder": "0.5", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "supabase_0-input-lambda-number" - } - ], - "inputAnchors": [ - { - "label": "Document", - "name": "document", - "type": "Document", - "list": true, - "optional": true, - "id": "supabase_0-input-document-Document" - }, - { - "label": "Embeddings", - "name": "embeddings", - "type": "Embeddings", - "id": "supabase_0-input-embeddings-Embeddings" - }, - { - "label": "Record Manager", - "name": "recordManager", - "type": "RecordManager", - "description": "Keep track of the record to prevent duplication", - "optional": true, - "id": "supabase_0-input-recordManager-RecordManager" - } - ], - "inputs": { - "document": "", - "embeddings": "{{openAIEmbeddings_0.data.instance}}", - "recordManager": "", - "supabaseProjUrl": "", - "tableName": "", - "queryName": "", - "supabaseMetadataFilter": "", - "supabaseRPCFilter": "", - "topK": "", - "searchType": "similarity", - "fetchK": "", - "lambda": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "description": "", - "options": [ - { - "id": "supabase_0-output-retriever-Supabase|VectorStoreRetriever|BaseRetriever", - "name": "retriever", - "label": "Supabase Retriever", - "description": "", - "type": "Supabase | VectorStoreRetriever | BaseRetriever" - }, - { - "id": "supabase_0-output-vectorStore-Supabase|VectorStore", - "name": "vectorStore", - "label": "Supabase Vector Store", - "description": "", - "type": "Supabase | VectorStore" - } - ], - "default": "retriever" - } - ], - "outputs": { - "output": "vectorStore" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 274.75982285806055, - "y": 982.5186034037372 - }, - "dragging": false - }, - { - "id": "stickyNote_0", - "position": { - "x": 1564.4709721348295, - "y": 121.26040803337389 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_0", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_0-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Multi Retrieval QA Chain is able to pick which Vector Store Retriever to use based on user question.\n\nHowever it comes with the restriction for not being able to resume follow up conversations because there isn't any memory.\n\nIt is suitable for LLM which doesn't have function calling support.\n\nOtherwise, it is recommended to use Multiple Documents QnA template which uses Tool Agent" - }, - "outputAnchors": [ - { - "id": "stickyNote_0-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 324, - "selected": false, - "positionAbsolute": { - "x": 1564.4709721348295, - "y": 121.26040803337389 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "vectorStoreRetriever_0", - "sourceHandle": "vectorStoreRetriever_0-output-vectorStoreRetriever-VectorStoreRetriever", - "target": "multiRetrievalQAChain_0", - "targetHandle": "multiRetrievalQAChain_0-input-vectorStoreRetriever-VectorStoreRetriever", - "type": "buttonedge", - "id": "vectorStoreRetriever_0-vectorStoreRetriever_0-output-vectorStoreRetriever-VectorStoreRetriever-multiRetrievalQAChain_0-multiRetrievalQAChain_0-input-vectorStoreRetriever-VectorStoreRetriever", - "data": { - "label": "" - } - }, - { - "source": "vectorStoreRetriever_1", - "sourceHandle": "vectorStoreRetriever_1-output-vectorStoreRetriever-VectorStoreRetriever", - "target": "multiRetrievalQAChain_0", - "targetHandle": "multiRetrievalQAChain_0-input-vectorStoreRetriever-VectorStoreRetriever", - "type": "buttonedge", - "id": "vectorStoreRetriever_1-vectorStoreRetriever_1-output-vectorStoreRetriever-VectorStoreRetriever-multiRetrievalQAChain_0-multiRetrievalQAChain_0-input-vectorStoreRetriever-VectorStoreRetriever", - "data": { - "label": "" - } - }, - { - "source": "vectorStoreRetriever_2", - "sourceHandle": "vectorStoreRetriever_2-output-vectorStoreRetriever-VectorStoreRetriever", - "target": "multiRetrievalQAChain_0", - "targetHandle": "multiRetrievalQAChain_0-input-vectorStoreRetriever-VectorStoreRetriever", - "type": "buttonedge", - "id": "vectorStoreRetriever_2-vectorStoreRetriever_2-output-vectorStoreRetriever-VectorStoreRetriever-multiRetrievalQAChain_0-multiRetrievalQAChain_0-input-vectorStoreRetriever-VectorStoreRetriever", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_0", - "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "multiRetrievalQAChain_0", - "targetHandle": "multiRetrievalQAChain_0-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-multiRetrievalQAChain_0-multiRetrievalQAChain_0-input-model-BaseLanguageModel", - "data": { - "label": "" - } - }, - { - "source": "pinecone_0", - "sourceHandle": "pinecone_0-output-vectorStore-Pinecone|VectorStore", - "target": "vectorStoreRetriever_2", - "targetHandle": "vectorStoreRetriever_2-input-vectorStore-VectorStore", - "type": "buttonedge", - "id": "pinecone_0-pinecone_0-output-vectorStore-Pinecone|VectorStore-vectorStoreRetriever_2-vectorStoreRetriever_2-input-vectorStore-VectorStore", - "data": { - "label": "" - } - }, - { - "source": "chroma_0", - "sourceHandle": "chroma_0-output-vectorStore-Chroma|VectorStore", - "target": "vectorStoreRetriever_1", - "targetHandle": "vectorStoreRetriever_1-input-vectorStore-VectorStore", - "type": "buttonedge", - "id": "chroma_0-chroma_0-output-vectorStore-Chroma|VectorStore-vectorStoreRetriever_1-vectorStoreRetriever_1-input-vectorStore-VectorStore", - "data": { - "label": "" - } - }, - { - "source": "supabase_0", - "sourceHandle": "supabase_0-output-vectorStore-Supabase|VectorStore", - "target": "vectorStoreRetriever_0", - "targetHandle": "vectorStoreRetriever_0-input-vectorStore-VectorStore", - "type": "buttonedge", - "id": "supabase_0-supabase_0-output-vectorStore-Supabase|VectorStore-vectorStoreRetriever_0-vectorStoreRetriever_0-input-vectorStore-VectorStore", - "data": { - "label": "" - } - }, - { - "source": "openAIEmbeddings_0", - "sourceHandle": "openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "target": "supabase_0", - "targetHandle": "supabase_0-input-embeddings-Embeddings", - "type": "buttonedge", - "id": "openAIEmbeddings_0-openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings-supabase_0-supabase_0-input-embeddings-Embeddings", - "data": { - "label": "" - } - }, - { - "source": "openAIEmbeddings_0", - "sourceHandle": "openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "target": "chroma_0", - "targetHandle": "chroma_0-input-embeddings-Embeddings", - "type": "buttonedge", - "id": "openAIEmbeddings_0-openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings-chroma_0-chroma_0-input-embeddings-Embeddings", - "data": { - "label": "" - } - }, - { - "source": "openAIEmbeddings_0", - "sourceHandle": "openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "target": "pinecone_0", - "targetHandle": "pinecone_0-input-embeddings-Embeddings", - "type": "buttonedge", - "id": "openAIEmbeddings_0-openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings-pinecone_0-pinecone_0-input-embeddings-Embeddings", - "data": { - "label": "" - } - } - ] -} diff --git a/packages/server/marketplaces/chatflows/Multiple Documents QnA.json b/packages/server/marketplaces/chatflows/Multiple Documents QnA.json index ff4d6b7f..46fdc99b 100644 --- a/packages/server/marketplaces/chatflows/Multiple Documents QnA.json +++ b/packages/server/marketplaces/chatflows/Multiple Documents QnA.json @@ -1,6 +1,5 @@ { "description": "Tool agent that can retrieve answers from multiple sources using relevant Retriever Tools", - "badge": "POPULAR", "usecases": ["Documents QnA"], "framework": ["Langchain"], "nodes": [ diff --git a/packages/server/marketplaces/chatflows/Multiple VectorDB.json b/packages/server/marketplaces/chatflows/Multiple VectorDB.json deleted file mode 100644 index d8e1e9e8..00000000 --- a/packages/server/marketplaces/chatflows/Multiple VectorDB.json +++ /dev/null @@ -1,1916 +0,0 @@ -{ - "description": "Conversational agent to choose between multiple Chain Tools, each connected to different vector databases", - "usecases": ["Documents QnA"], - "framework": ["Langchain"], - "nodes": [ - { - "width": 300, - "height": 603, - "id": "chainTool_2", - "position": { - "x": 1274.762717089282, - "y": -955.2604402500798 - }, - "type": "customNode", - "data": { - "id": "chainTool_2", - "label": "Chain Tool", - "version": 1, - "name": "chainTool", - "type": "ChainTool", - "baseClasses": ["ChainTool", "DynamicTool", "Tool", "StructuredTool", "BaseLangChain"], - "category": "Tools", - "description": "Use a chain as allowed tool for agent", - "inputParams": [ - { - "label": "Chain Name", - "name": "name", - "type": "string", - "placeholder": "state-of-union-qa", - "id": "chainTool_2-input-name-string" - }, - { - "label": "Chain Description", - "name": "description", - "type": "string", - "rows": 3, - "placeholder": "State of the Union QA - useful for when you need to ask questions about the most recent state of the union address.", - "id": "chainTool_2-input-description-string" - }, - { - "label": "Return Direct", - "name": "returnDirect", - "type": "boolean", - "optional": true, - "id": "chainTool_2-input-returnDirect-boolean" - } - ], - "inputAnchors": [ - { - "label": "Base Chain", - "name": "baseChain", - "type": "BaseChain", - "id": "chainTool_2-input-baseChain-BaseChain" - } - ], - "inputs": { - "name": "ai-paper-qa", - "description": "AI Paper QA - useful for when you need to ask questions about the AI-Generated Content paper.", - "returnDirect": true, - "baseChain": "{{retrievalQAChain_0.data.instance}}" - }, - "outputAnchors": [ - { - "id": "chainTool_2-output-chainTool-ChainTool|DynamicTool|Tool|StructuredTool|BaseLangChain", - "name": "chainTool", - "label": "ChainTool", - "type": "ChainTool | DynamicTool | Tool | StructuredTool | BaseLangChain" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1274.762717089282, - "y": -955.2604402500798 - }, - "dragging": false - }, - { - "width": 300, - "height": 603, - "id": "chainTool_3", - "position": { - "x": 1278.5582632273515, - "y": -214.68611013834368 - }, - "type": "customNode", - "data": { - "id": "chainTool_3", - "label": "Chain Tool", - "version": 1, - "name": "chainTool", - "type": "ChainTool", - "baseClasses": ["ChainTool", "DynamicTool", "Tool", "StructuredTool", "BaseLangChain"], - "category": "Tools", - "description": "Use a chain as allowed tool for agent", - "inputParams": [ - { - "label": "Chain Name", - "name": "name", - "type": "string", - "placeholder": "state-of-union-qa", - "id": "chainTool_3-input-name-string" - }, - { - "label": "Chain Description", - "name": "description", - "type": "string", - "rows": 3, - "placeholder": "State of the Union QA - useful for when you need to ask questions about the most recent state of the union address.", - "id": "chainTool_3-input-description-string" - }, - { - "label": "Return Direct", - "name": "returnDirect", - "type": "boolean", - "optional": true, - "id": "chainTool_3-input-returnDirect-boolean" - } - ], - "inputAnchors": [ - { - "label": "Base Chain", - "name": "baseChain", - "type": "BaseChain", - "id": "chainTool_3-input-baseChain-BaseChain" - } - ], - "inputs": { - "name": "state-of-union-qa", - "description": "State of the Union QA - useful for when you need to ask questions about the president speech and most recent state of the union address.", - "returnDirect": true, - "baseChain": "{{retrievalQAChain_1.data.instance}}" - }, - "outputAnchors": [ - { - "id": "chainTool_3-output-chainTool-ChainTool|DynamicTool|Tool|StructuredTool|BaseLangChain", - "name": "chainTool", - "label": "ChainTool", - "type": "ChainTool | DynamicTool | Tool | StructuredTool | BaseLangChain" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "dragging": false, - "positionAbsolute": { - "x": 1278.5582632273515, - "y": -214.68611013834368 - } - }, - { - "width": 300, - "height": 332, - "id": "retrievalQAChain_0", - "position": { - "x": 898.1253096948574, - "y": -859.1174013418433 - }, - "type": "customNode", - "data": { - "id": "retrievalQAChain_0", - "label": "Retrieval QA Chain", - "version": 2, - "name": "retrievalQAChain", - "type": "RetrievalQAChain", - "baseClasses": ["RetrievalQAChain", "BaseChain", "BaseLangChain"], - "category": "Chains", - "description": "QA chain to answer a question based on the retrieved documents", - "inputParams": [], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "retrievalQAChain_0-input-model-BaseLanguageModel" - }, - { - "label": "Vector Store Retriever", - "name": "vectorStoreRetriever", - "type": "BaseRetriever", - "id": "retrievalQAChain_0-input-vectorStoreRetriever-BaseRetriever" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "retrievalQAChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "inputModeration": "", - "model": "{{chatOpenAI_0.data.instance}}", - "vectorStoreRetriever": "{{redis_0.data.instance}}" - }, - "outputAnchors": [ - { - "id": "retrievalQAChain_0-output-retrievalQAChain-RetrievalQAChain|BaseChain|BaseLangChain", - "name": "retrievalQAChain", - "label": "RetrievalQAChain", - "type": "RetrievalQAChain | BaseChain | BaseLangChain" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 898.1253096948574, - "y": -859.1174013418433 - }, - "dragging": false - }, - { - "width": 300, - "height": 332, - "id": "retrievalQAChain_1", - "position": { - "x": 920.057949591115, - "y": 268.2828817441888 - }, - "type": "customNode", - "data": { - "id": "retrievalQAChain_1", - "label": "Retrieval QA Chain", - "version": 2, - "name": "retrievalQAChain", - "type": "RetrievalQAChain", - "baseClasses": ["RetrievalQAChain", "BaseChain", "BaseLangChain"], - "category": "Chains", - "description": "QA chain to answer a question based on the retrieved documents", - "inputParams": [], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "retrievalQAChain_1-input-model-BaseLanguageModel" - }, - { - "label": "Vector Store Retriever", - "name": "vectorStoreRetriever", - "type": "BaseRetriever", - "id": "retrievalQAChain_1-input-vectorStoreRetriever-BaseRetriever" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "retrievalQAChain_1-input-inputModeration-Moderation" - } - ], - "inputs": { - "inputModeration": "", - "model": "{{chatOpenAI_1.data.instance}}", - "vectorStoreRetriever": "{{faiss_0.data.instance}}" - }, - "outputAnchors": [ - { - "id": "retrievalQAChain_1-output-retrievalQAChain-RetrievalQAChain|BaseChain|BaseLangChain", - "name": "retrievalQAChain", - "label": "RetrievalQAChain", - "type": "RetrievalQAChain | BaseChain | BaseLangChain" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 920.057949591115, - "y": 268.2828817441888 - }, - "dragging": false - }, - { - "width": 300, - "height": 424, - "id": "openAIEmbeddings_1", - "position": { - "x": 100.06006551346672, - "y": -686.9997729064416 - }, - "type": "customNode", - "data": { - "id": "openAIEmbeddings_1", - "label": "OpenAI Embeddings", - "version": 4, - "name": "openAIEmbeddings", - "type": "OpenAIEmbeddings", - "baseClasses": ["OpenAIEmbeddings", "Embeddings"], - "category": "Embeddings", - "description": "OpenAI API to generate embeddings for a given text", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "openAIEmbeddings_1-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "text-embedding-ada-002", - "id": "openAIEmbeddings_1-input-modelName-asyncOptions" - }, - { - "label": "Strip New Lines", - "name": "stripNewLines", - "type": "boolean", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_1-input-stripNewLines-boolean" - }, - { - "label": "Batch Size", - "name": "batchSize", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_1-input-batchSize-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_1-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_1-input-basepath-string" - }, - { - "label": "Dimensions", - "name": "dimensions", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_1-input-dimensions-number" - } - ], - "inputAnchors": [], - "inputs": { - "modelName": "text-embedding-ada-002", - "stripNewLines": "", - "batchSize": "", - "timeout": "", - "basepath": "", - "dimensions": "" - }, - "outputAnchors": [ - { - "id": "openAIEmbeddings_1-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "name": "openAIEmbeddings", - "label": "OpenAIEmbeddings", - "description": "OpenAI API to generate embeddings for a given text", - "type": "OpenAIEmbeddings | Embeddings" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 100.06006551346672, - "y": -686.9997729064416 - }, - "dragging": false - }, - { - "width": 300, - "height": 424, - "id": "openAIEmbeddings_2", - "position": { - "x": 126.74109446437771, - "y": 542.6301053870723 - }, - "type": "customNode", - "data": { - "id": "openAIEmbeddings_2", - "label": "OpenAI Embeddings", - "version": 4, - "name": "openAIEmbeddings", - "type": "OpenAIEmbeddings", - "baseClasses": ["OpenAIEmbeddings", "Embeddings"], - "category": "Embeddings", - "description": "OpenAI API to generate embeddings for a given text", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "openAIEmbeddings_2-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "text-embedding-ada-002", - "id": "openAIEmbeddings_2-input-modelName-asyncOptions" - }, - { - "label": "Strip New Lines", - "name": "stripNewLines", - "type": "boolean", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_2-input-stripNewLines-boolean" - }, - { - "label": "Batch Size", - "name": "batchSize", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_2-input-batchSize-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_2-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_2-input-basepath-string" - }, - { - "label": "Dimensions", - "name": "dimensions", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_2-input-dimensions-number" - } - ], - "inputAnchors": [], - "inputs": { - "modelName": "text-embedding-ada-002", - "stripNewLines": "", - "batchSize": "", - "timeout": "", - "basepath": "", - "dimensions": "" - }, - "outputAnchors": [ - { - "id": "openAIEmbeddings_2-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "name": "openAIEmbeddings", - "label": "OpenAIEmbeddings", - "description": "OpenAI API to generate embeddings for a given text", - "type": "OpenAIEmbeddings | Embeddings" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 126.74109446437771, - "y": 542.6301053870723 - }, - "dragging": false - }, - { - "width": 300, - "height": 670, - "id": "chatOpenAI_0", - "position": { - "x": 519.798956186608, - "y": -1601.3893918503904 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_0", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_0-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_0-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_0-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_0-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo-16k", - "temperature": 0.9, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 519.798956186608, - "y": -1601.3893918503904 - }, - "dragging": false - }, - { - "width": 300, - "height": 652, - "id": "redis_0", - "position": { - "x": 517.9599892124863, - "y": -892.797784079465 - }, - "type": "customNode", - "data": { - "id": "redis_0", - "label": "Redis", - "version": 1, - "name": "redis", - "type": "Redis", - "baseClasses": ["Redis", "VectorStoreRetriever", "BaseRetriever"], - "category": "Vector Stores", - "description": "Upsert embedded data and perform similarity search upon query using Redis, an open source, in-memory data structure store", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["redisCacheUrlApi", "redisCacheApi"], - "id": "redis_0-input-credential-credential" - }, - { - "label": "Index Name", - "name": "indexName", - "placeholder": "", - "type": "string", - "id": "redis_0-input-indexName-string" - }, - { - "label": "Replace Index on Upsert", - "name": "replaceIndex", - "description": "Selecting this option will delete the existing index and recreate a new one when upserting", - "default": false, - "type": "boolean", - "id": "redis_0-input-replaceIndex-boolean" - }, - { - "label": "Content Field", - "name": "contentKey", - "description": "Name of the field (column) that contains the actual content", - "type": "string", - "default": "content", - "additionalParams": true, - "optional": true, - "id": "redis_0-input-contentKey-string" - }, - { - "label": "Metadata Field", - "name": "metadataKey", - "description": "Name of the field (column) that contains the metadata of the document", - "type": "string", - "default": "metadata", - "additionalParams": true, - "optional": true, - "id": "redis_0-input-metadataKey-string" - }, - { - "label": "Vector Field", - "name": "vectorKey", - "description": "Name of the field (column) that contains the vector", - "type": "string", - "default": "content_vector", - "additionalParams": true, - "optional": true, - "id": "redis_0-input-vectorKey-string" - }, - { - "label": "Top K", - "name": "topK", - "description": "Number of top results to fetch. Default to 4", - "placeholder": "4", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "redis_0-input-topK-number" - } - ], - "inputAnchors": [ - { - "label": "Document", - "name": "document", - "type": "Document", - "list": true, - "optional": true, - "id": "redis_0-input-document-Document" - }, - { - "label": "Embeddings", - "name": "embeddings", - "type": "Embeddings", - "id": "redis_0-input-embeddings-Embeddings" - } - ], - "inputs": { - "document": ["{{plainText_0.data.instance}}"], - "embeddings": "{{openAIEmbeddings_1.data.instance}}", - "indexName": "redis-1234", - "replaceIndex": true, - "contentKey": "content", - "metadataKey": "metadata", - "vectorKey": "content_vector", - "topK": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "redis_0-output-retriever-Redis|VectorStoreRetriever|BaseRetriever", - "name": "retriever", - "label": "Redis Retriever", - "type": "Redis | VectorStoreRetriever | BaseRetriever" - }, - { - "id": "redis_0-output-vectorStore-Redis|VectorStore", - "name": "vectorStore", - "label": "Redis Vector Store", - "type": "Redis | VectorStore" - } - ], - "default": "retriever" - } - ], - "outputs": { - "output": "retriever" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 517.9599892124863, - "y": -892.797784079465 - }, - "dragging": false - }, - { - "width": 300, - "height": 459, - "id": "faiss_0", - "position": { - "x": 537.5298173812396, - "y": 545.504276022315 - }, - "type": "customNode", - "data": { - "id": "faiss_0", - "label": "Faiss", - "version": 1, - "name": "faiss", - "type": "Faiss", - "baseClasses": ["Faiss", "VectorStoreRetriever", "BaseRetriever"], - "category": "Vector Stores", - "description": "Upsert embedded data and perform similarity search upon query using Faiss library from Meta", - "inputParams": [ - { - "label": "Base Path to load", - "name": "basePath", - "description": "Path to load faiss.index file", - "placeholder": "C:\\Users\\User\\Desktop", - "type": "string", - "id": "faiss_0-input-basePath-string" - }, - { - "label": "Top K", - "name": "topK", - "description": "Number of top results to fetch. Default to 4", - "placeholder": "4", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "faiss_0-input-topK-number" - } - ], - "inputAnchors": [ - { - "label": "Document", - "name": "document", - "type": "Document", - "list": true, - "optional": true, - "id": "faiss_0-input-document-Document" - }, - { - "label": "Embeddings", - "name": "embeddings", - "type": "Embeddings", - "id": "faiss_0-input-embeddings-Embeddings" - } - ], - "inputs": { - "document": ["{{plainText_1.data.instance}}"], - "embeddings": "{{openAIEmbeddings_2.data.instance}}", - "basePath": "C:\\Users\\user\\yourpath", - "topK": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "faiss_0-output-retriever-Faiss|VectorStoreRetriever|BaseRetriever", - "name": "retriever", - "label": "Faiss Retriever", - "type": "Faiss | VectorStoreRetriever | BaseRetriever" - }, - { - "id": "faiss_0-output-vectorStore-Faiss|SaveableVectorStore|VectorStore", - "name": "vectorStore", - "label": "Faiss Vector Store", - "type": "Faiss | SaveableVectorStore | VectorStore" - } - ], - "default": "retriever" - } - ], - "outputs": { - "output": "retriever" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 537.5298173812396, - "y": 545.504276022315 - }, - "dragging": false - }, - { - "width": 300, - "height": 487, - "id": "plainText_0", - "position": { - "x": 93.6260931892966, - "y": -1209.0760064103088 - }, - "type": "customNode", - "data": { - "id": "plainText_0", - "label": "Plain Text", - "version": 2, - "name": "plainText", - "type": "Document", - "baseClasses": ["Document"], - "category": "Document Loaders", - "description": "Load data from plain text", - "inputParams": [ - { - "label": "Text", - "name": "text", - "type": "string", - "rows": 4, - "placeholder": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...", - "id": "plainText_0-input-text-string" - }, - { - "label": "Metadata", - "name": "metadata", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "plainText_0-input-metadata-json" - } - ], - "inputAnchors": [ - { - "label": "Text Splitter", - "name": "textSplitter", - "type": "TextSplitter", - "optional": true, - "id": "plainText_0-input-textSplitter-TextSplitter" - } - ], - "inputs": { - "text": "AI-generated content refers to text, images, videos, or other media produced by artificial intelligence algorithms. It leverages deep learning and natural language processing to create human-like content autonomously. AI-generated content has diverse applications, from automated customer support chatbots and personalized marketing to creative writing and art generation. While it offers efficiency and scalability, it also raises concerns about ethics, authenticity, and potential misuse. Striking a balance between harnessing its potential for productivity and addressing its ethical implications is crucial as AI-generated content continues to evolve and reshape industries.", - "textSplitter": "", - "metadata": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "plainText_0-output-document-Document|json", - "name": "document", - "label": "Document", - "type": "Document | json" - }, - { - "id": "plainText_0-output-text-string|json", - "name": "text", - "label": "Text", - "type": "string | json" - } - ], - "default": "document" - } - ], - "outputs": { - "output": "document" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 93.6260931892966, - "y": -1209.0760064103088 - }, - "dragging": false - }, - { - "width": 300, - "height": 670, - "id": "chatOpenAI_1", - "position": { - "x": 533.0416474070086, - "y": -168.63117374104695 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_1", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_1-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_1-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_1-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_1-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_1-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_1-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo-16k", - "temperature": 0.9, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 533.0416474070086, - "y": -168.63117374104695 - }, - "dragging": false - }, - { - "width": 300, - "height": 253, - "id": "bufferMemory_0", - "position": { - "x": 2047.6821632337533, - "y": 429.48576006102945 - }, - "type": "customNode", - "data": { - "id": "bufferMemory_0", - "label": "Buffer Memory", - "version": 2, - "name": "bufferMemory", - "type": "BufferMemory", - "baseClasses": ["BufferMemory", "BaseChatMemory", "BaseMemory"], - "category": "Memory", - "description": "Retrieve chat messages stored in database", - "inputParams": [ - { - "label": "Session Id", - "name": "sessionId", - "type": "string", - "description": "If not specified, a random id will be used. Learn more", - "default": "", - "additionalParams": true, - "optional": true, - "id": "bufferMemory_0-input-sessionId-string" - }, - { - "label": "Memory Key", - "name": "memoryKey", - "type": "string", - "default": "chat_history", - "additionalParams": true, - "id": "bufferMemory_0-input-memoryKey-string" - } - ], - "inputAnchors": [], - "inputs": { - "sessionId": "", - "memoryKey": "chat_history" - }, - "outputAnchors": [ - { - "id": "bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory", - "name": "bufferMemory", - "label": "BufferMemory", - "type": "BufferMemory | BaseChatMemory | BaseMemory" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 2047.6821632337533, - "y": 429.48576006102945 - }, - "dragging": false - }, - { - "width": 300, - "height": 487, - "id": "plainText_1", - "position": { - "x": 117.23894449422778, - "y": 23.24339894687961 - }, - "type": "customNode", - "data": { - "id": "plainText_1", - "label": "Plain Text", - "version": 2, - "name": "plainText", - "type": "Document", - "baseClasses": ["Document"], - "category": "Document Loaders", - "description": "Load data from plain text", - "inputParams": [ - { - "label": "Text", - "name": "text", - "type": "string", - "rows": 4, - "placeholder": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...", - "id": "plainText_1-input-text-string" - }, - { - "label": "Metadata", - "name": "metadata", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "plainText_1-input-metadata-json" - } - ], - "inputAnchors": [ - { - "label": "Text Splitter", - "name": "textSplitter", - "type": "TextSplitter", - "optional": true, - "id": "plainText_1-input-textSplitter-TextSplitter" - } - ], - "inputs": { - "text": "Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans. \n\nLast year COVID-19 kept us apart. This year we are finally together again. \n\nTonight, we meet as Democrats Republicans and Independents. But most importantly as Americans. \n\nWith a duty to one another to the American people to the Constitution. \n\nAnd with an unwavering resolve that freedom will always triumph over tyranny. \n\nSix days ago, Russia’s Vladimir Putin sought to shake the foundations of the free world thinking he could make it bend to his menacing ways. But he badly miscalculated. \n\nHe thought he could roll into Ukraine and the world would roll over. Instead he met a wall of strength he never imagined. \n\nHe met the Ukrainian people. \n\nFrom President Zelenskyy to every Ukrainian, their fearlessness, their courage, their determination, inspires the world. \n\nGroups of citizens blocking tanks with their bodies. Everyone from students to retirees teachers turned soldiers defending their homeland. \n\nIn this struggle as President Zelenskyy said in his speech to the European Parliament “Light will win over darkness.” The Ukrainian Ambassador to the United States is here tonight. \n\nLet each of us here tonight in this Chamber send an unmistakable signal to Ukraine and to the world. \n\nPlease rise if you are able and show that, Yes, we the United States of America stand with the Ukrainian people. \n\nThroughout our history we’ve learned this lesson when dictators do not pay a price for their aggression they cause more chaos. \n\nThey keep moving. \n\nAnd the costs and the threats to America and the world keep rising. \n\nThat’s why the NATO Alliance was created to secure peace and stability in Europe after World War 2. \n\nThe United States is a member along with 29 other nations. \n\nIt matters. American diplomacy matters. American resolve matters. \n\nPutin’s latest attack on Ukraine was premeditated and unprovoked. \n\nHe rejected repeated efforts at diplomacy. \n\nHe thought the West and NATO wouldn’t respond. And he thought he could divide us at home. Putin was wrong. We were ready. Here is what we did. \n\nWe prepared extensively and carefully. \n\nWe spent months building a coalition of other freedom-loving nations from Europe and the Americas to Asia and Africa to confront Putin. \n\nI spent countless hours unifying our European allies. We shared with the world in advance what we knew Putin was planning and precisely how he would try to falsely justify his aggression. \n\nWe countered Russia’s lies with truth. \n\nAnd now that he has acted the free world is holding him accountable. \n\nAlong with twenty-seven members of the European Union including France, Germany, Italy, as well as countries like the United Kingdom, Canada, Japan, Korea, Australia, New Zealand, and many others, even Switzerland. \n\nWe are inflicting pain on Russia and supporting the people of Ukraine. Putin is now isolated from the world more than ever. \n\nTogether with our allies –we are right now enforcing powerful economic sanctions. \n\nWe are cutting off Russia’s largest banks from the international financial system. \n\nPreventing Russia’s central bank from defending the Russian Ruble making Putin’s $630 Billion “war fund” worthless. \n\nWe are choking off Russia’s access to technology that will sap its economic strength and weaken its military for years to come. \n\nTonight I say to the Russian oligarchs and corrupt leaders who have bilked billions of dollars off this violent regime no more. \n\nThe U.S. Department of Justice is assembling a dedicated task force to go after the crimes of Russian oligarchs. \n\nWe are joining with our European allies to find and seize your yachts your luxury apartments your private jets. We are coming for your ill-begotten gains. \n\nAnd tonight I am announcing that we will join our allies in closing off American air space to all Russian flights – further isolating Russia – and adding an additional squeeze –on their economy. The Ruble has lost 30% of its value. \n\nThe Russian stock market has lost 40% of its value and trading remains suspended. Russia’s economy is reeling and Putin alone is to blame. \n\nTogether with our allies we are providing support to the Ukrainians in their fight for freedom. Military assistance. Economic assistance. Humanitarian assistance. \n\nWe are giving more than $1 Billion in direct assistance to Ukraine. \n\nAnd we will continue to aid the Ukrainian people as they defend their country and to help ease their suffering. \n\nLet me be clear, our forces are not engaged and will not engage in conflict with Russian forces in Ukraine. \n\nOur forces are not going to Europe to fight in Ukraine, but to defend our NATO Allies – in the event that Putin decides to keep moving west. \n\nFor that purpose we’ve mobilized American ground forces, air squadrons, and ship deployments to protect NATO countries including Poland, Romania, Latvia, Lithuania, and Estonia. \n\nAs I have made crystal clear the United States and our Allies will defend every inch of territory of NATO countries with the full force of our collective power. \n\nAnd we remain clear-eyed. The Ukrainians are fighting back with pure courage. But the next few days weeks, months, will be hard on them. \n\nPutin has unleashed violence and chaos. But while he may make gains on the battlefield – he will pay a continuing high price over the long run. \n\nAnd a proud Ukrainian people, who have known 30 years of independence, have repeatedly shown that they will not tolerate anyone who tries to take their country backwards. \n\nTo all Americans, I will be honest with you, as I’ve always promised. A Russian dictator, invading a foreign country, has costs around the world. \n\nAnd I’m taking robust action to make sure the pain of our sanctions is targeted at Russia’s economy. And I will use every tool at our disposal to protect American businesses and consumers. \n\nTonight, I can announce that the United States has worked with 30 other countries to release 60 Million barrels of oil from reserves around the world. \n\nAmerica will lead that effort, releasing 30 Million barrels from our own Strategic Petroleum Reserve. And we stand ready to do more if necessary, unified with our allies. \n\nThese steps will help blunt gas prices here at home. And I know the news about what’s happening can seem alarming. \n\nBut I want you to know that we are going to be okay. \n\nWhen the history of this era is written Putin’s war on Ukraine will have left Russia weaker and the rest of the world stronger. \n\nWhile it shouldn’t have taken something so terrible for people around the world to see what’s at stake now everyone sees it clearly. \n\nWe see the unity among leaders of nations and a more unified Europe a more unified West. And we see unity among the people who are gathering in cities in large crowds around the world even in Russia to demonstrate their support for Ukraine. \n\nIn the battle between democracy and autocracy, democracies are rising to the moment, and the world is clearly choosing the side of peace and security. \n\nThis is a real test. It’s going to take time. So let us continue to draw inspiration from the iron will of the Ukrainian people. \n\nTo our fellow Ukrainian Americans who forge a deep bond that connects our two nations we stand with you. \n\nPutin may circle Kyiv with tanks, but he will never gain the hearts and souls of the Ukrainian people. \n\nHe will never extinguish their love of freedom. He will never weaken the resolve of the free world. \n\nWe meet tonight in an America that has lived through two of the hardest years this nation has ever faced. \n\nThe pandemic has been punishing. \n\nAnd so many families are living paycheck to paycheck, struggling to keep up with the rising cost of food, gas, housing, and so much more. \n\nI understand. \n\nI remember when my Dad had to leave our home in Scranton, Pennsylvania to find work. I grew up in a family where if the price of food went up, you felt it. \n\nThat’s why one of the first things I did as President was fight to pass the American Rescue Plan. \n\nBecause people were hurting. We needed to act, and we did. \n\nFew pieces of legislation have done more in a critical moment in our history to lift us out of crisis. \n\nIt fueled our efforts to vaccinate the nation and combat COVID-19. It delivered immediate economic relief for tens of millions of Americans. \n\nHelped put food on their table, keep a roof over their heads, and cut the cost of health insurance. \n\nAnd as my Dad used to say, it gave people a little breathing room. \n\nAnd unlike the $2 Trillion tax cut passed in the previous administration that benefitted the top 1% of Americans, the American Rescue Plan helped working people—and left no one behind. \n\nAnd it worked. It created jobs. Lots of jobs. \n\nIn fact—our economy created over 6.5 Million new jobs just last year, more jobs created in one year \nthan ever before in the history of America. \n\nOur economy grew at a rate of 5.7% last year, the strongest growth in nearly 40 years, the first step in bringing fundamental change to an economy that hasn’t worked for the working people of this nation for too long. \n\nFor the past 40 years we were told that if we gave tax breaks to those at the very top, the benefits would trickle down to everyone else. \n\nBut that trickle-down theory led to weaker economic growth, lower wages, bigger deficits, and the widest gap between those at the top and everyone else in nearly a century. \n\nVice President Harris and I ran for office with a new economic vision for America. \n\nInvest in America. Educate Americans. Grow the workforce. Build the economy from the bottom up \nand the middle out, not from the top down. \n\nBecause we know that when the middle class grows, the poor have a ladder up and the wealthy do very well. \n\nAmerica used to have the best roads, bridges, and airports on Earth. \n\nNow our infrastructure is ranked 13th in the world. \n\nWe won’t be able to compete for the jobs of the 21st Century if we don’t fix that. \n\nThat’s why it was so important to pass the Bipartisan Infrastructure Law—the most sweeping investment to rebuild America in history. \n\nThis was a bipartisan effort, and I want to thank the members of both parties who worked to make it happen. \n\nWe’re done talking about infrastructure weeks. \n\nWe’re going to have an infrastructure decade. \n\nIt is going to transform America and put us on a path to win the economic competition of the 21st Century that we face with the rest of the world—particularly with China. \n\nAs I’ve told Xi Jinping, it is never a good bet to bet against the American people. \n\nWe’ll create good jobs for millions of Americans, modernizing roads, airports, ports, and waterways all across America. \n\nAnd we’ll do it all to withstand the devastating effects of the climate crisis and promote environmental justice. \n\nWe’ll build a national network of 500,000 electric vehicle charging stations, begin to replace poisonous lead pipes—so every child—and every American—has clean water to drink at home and at school, provide affordable high-speed internet for every American—urban, suburban, rural, and tribal communities. \n\n4,000 projects have already been announced. \n\nAnd tonight, I’m announcing that this year we will start fixing over 65,000 miles of highway and 1,500 bridges in disrepair. \n\nWhen we use taxpayer dollars to rebuild America – we are going to Buy American: buy American products to support American jobs. \n\nThe federal government spends about $600 Billion a year to keep the country safe and secure. \n\nThere’s been a law on the books for almost a century \nto make sure taxpayers’ dollars support American jobs and businesses. \n\nEvery Administration says they’ll do it, but we are actually doing it. \n\nWe will buy American to make sure everything from the deck of an aircraft carrier to the steel on highway guardrails are made in America. \n\nBut to compete for the best jobs of the future, we also need to level the playing field with China and other competitors. \n\nThat’s why it is so important to pass the Bipartisan Innovation Act sitting in Congress that will make record investments in emerging technologies and American manufacturing. \n\nLet me give you one example of why it’s so important to pass it. \n\nIf you travel 20 miles east of Columbus, Ohio, you’ll find 1,000 empty acres of land. \n\nIt won’t look like much, but if you stop and look closely, you’ll see a “Field of dreams,” the ground on which America’s future will be built. \n\nThis is where Intel, the American company that helped build Silicon Valley, is going to build its $20 billion semiconductor “mega site”. \n\nUp to eight state-of-the-art factories in one place. 10,000 new good-paying jobs. \n\nSome of the most sophisticated manufacturing in the world to make computer chips the size of a fingertip that power the world and our everyday lives. \n\nSmartphones. The Internet. Technology we have yet to invent. \n\nBut that’s just the beginning. \n\nIntel’s CEO, Pat Gelsinger, who is here tonight, told me they are ready to increase their investment from \n$20 billion to $100 billion. \n\nThat would be one of the biggest investments in manufacturing in American history. \n\nAnd all they’re waiting for is for you to pass this bill. \n\nSo let’s not wait any longer. Send it to my desk. I’ll sign it. \n\nAnd we will really take off. \n\nAnd Intel is not alone. \n\nThere’s something happening in America. \n\nJust look around and you’ll see an amazing story. \n\nThe rebirth of the pride that comes from stamping products “Made In America.” The revitalization of American manufacturing. \n\nCompanies are choosing to build new factories here, when just a few years ago, they would have built them overseas. \n\nThat’s what is happening. Ford is investing $11 billion to build electric vehicles, creating 11,000 jobs across the country. \n\nGM is making the largest investment in its history—$7 billion to build electric vehicles, creating 4,000 jobs in Michigan. \n\nAll told, we created 369,000 new manufacturing jobs in America just last year. \n\nPowered by people I’ve met like JoJo Burgess, from generations of union steelworkers from Pittsburgh, who’s here with us tonight. \n\nAs Ohio Senator Sherrod Brown says, “It’s time to bury the label “Rust Belt.” \n\nIt’s time. \n\nBut with all the bright spots in our economy, record job growth and higher wages, too many families are struggling to keep up with the bills. \n\nInflation is robbing them of the gains they might otherwise feel. \n\nI get it. That’s why my top priority is getting prices under control. \n\nLook, our economy roared back faster than most predicted, but the pandemic meant that businesses had a hard time hiring enough workers to keep up production in their factories. \n\nThe pandemic also disrupted global supply chains. \n\nWhen factories close, it takes longer to make goods and get them from the warehouse to the store, and prices go up. \n\nLook at cars. \n\nLast year, there weren’t enough semiconductors to make all the cars that people wanted to buy. \n\nAnd guess what, prices of automobiles went up. \n\nSo—we have a choice. \n\nOne way to fight inflation is to drive down wages and make Americans poorer. \n\nI have a better plan to fight inflation. \n\nLower your costs, not your wages. \n\nMake more cars and semiconductors in America. \n\nMore infrastructure and innovation in America. \n\nMore goods moving faster and cheaper in America. \n\nMore jobs where you can earn a good living in America. \n\nAnd instead of relying on foreign supply chains, let’s make it in America. \n\nEconomists call it “increasing the productive capacity of our economy.” \n\nI call it building a better America. \n\nMy plan to fight inflation will lower your costs and lower the deficit. \n\n17 Nobel laureates in economics say my plan will ease long-term inflationary pressures. Top business leaders and most Americans support my plan. And here’s the plan: \n\nFirst – cut the cost of prescription drugs. Just look at insulin. One in ten Americans has diabetes. In Virginia, I met a 13-year-old boy named Joshua Davis. \n\nHe and his Dad both have Type 1 diabetes, which means they need insulin every day. Insulin costs about $10 a vial to make. \n\nBut drug companies charge families like Joshua and his Dad up to 30 times more. I spoke with Joshua’s mom. \n\nImagine what it’s like to look at your child who needs insulin and have no idea how you’re going to pay for it. \n\nWhat it does to your dignity, your ability to look your child in the eye, to be the parent you expect to be. \n\nJoshua is here with us tonight. Yesterday was his birthday. Happy birthday, buddy. \n\nFor Joshua, and for the 200,000 other young people with Type 1 diabetes, let’s cap the cost of insulin at $35 a month so everyone can afford it. \n\nDrug companies will still do very well. And while we’re at it let Medicare negotiate lower prices for prescription drugs, like the VA already does. \n\nLook, the American Rescue Plan is helping millions of families on Affordable Care Act plans save $2,400 a year on their health care premiums. Let’s close the coverage gap and make those savings permanent. \n\nSecond – cut energy costs for families an average of $500 a year by combatting climate change. \n\nLet’s provide investments and tax credits to weatherize your homes and businesses to be energy efficient and you get a tax credit; double America’s clean energy production in solar, wind, and so much more; lower the price of electric vehicles, saving you another $80 a month because you’ll never have to pay at the gas pump again. \n\nThird – cut the cost of child care. Many families pay up to $14,000 a year for child care per child. \n\nMiddle-class and working families shouldn’t have to pay more than 7% of their income for care of young children. \n\nMy plan will cut the cost in half for most families and help parents, including millions of women, who left the workforce during the pandemic because they couldn’t afford child care, to be able to get back to work. \n\nMy plan doesn’t stop there. It also includes home and long-term care. More affordable housing. And Pre-K for every 3- and 4-year-old. \n\nAll of these will lower costs. \n\nAnd under my plan, nobody earning less than $400,000 a year will pay an additional penny in new taxes. Nobody. \n\nThe one thing all Americans agree on is that the tax system is not fair. We have to fix it. \n\nI’m not looking to punish anyone. But let’s make sure corporations and the wealthiest Americans start paying their fair share. \n\nJust last year, 55 Fortune 500 corporations earned $40 billion in profits and paid zero dollars in federal income tax. \n\nThat’s simply not fair. That’s why I’ve proposed a 15% minimum tax rate for corporations. \n\nWe got more than 130 countries to agree on a global minimum tax rate so companies can’t get out of paying their taxes at home by shipping jobs and factories overseas. \n\nThat’s why I’ve proposed closing loopholes so the very wealthy don’t pay a lower tax rate than a teacher or a firefighter. \n\nSo that’s my plan. It will grow the economy and lower costs for families. \n\nSo what are we waiting for? Let’s get this done. And while you’re at it, confirm my nominees to the Federal Reserve, which plays a critical role in fighting inflation. \n\nMy plan will not only lower costs to give families a fair shot, it will lower the deficit. \n\nThe previous Administration not only ballooned the deficit with tax cuts for the very wealthy and corporations, it undermined the watchdogs whose job was to keep pandemic relief funds from being wasted. \n\nBut in my administration, the watchdogs have been welcomed back. \n\nWe’re going after the criminals who stole billions in relief money meant for small businesses and millions of Americans. \n\nAnd tonight, I’m announcing that the Justice Department will name a chief prosecutor for pandemic fraud. \n\nBy the end of this year, the deficit will be down to less than half what it was before I took office. \n\nThe only president ever to cut the deficit by more than one trillion dollars in a single year. \n\nLowering your costs also means demanding more competition. \n\nI’m a capitalist, but capitalism without competition isn’t capitalism. \n\nIt’s exploitation—and it drives up prices. \n\nWhen corporations don’t have to compete, their profits go up, your prices go up, and small businesses and family farmers and ranchers go under. \n\nWe see it happening with ocean carriers moving goods in and out of America. \n\nDuring the pandemic, these foreign-owned companies raised prices by as much as 1,000% and made record profits. \n\nTonight, I’m announcing a crackdown on these companies overcharging American businesses and consumers. \n\nAnd as Wall Street firms take over more nursing homes, quality in those homes has gone down and costs have gone up. \n\nThat ends on my watch. \n\nMedicare is going to set higher standards for nursing homes and make sure your loved ones get the care they deserve and expect. \n\nWe’ll also cut costs and keep the economy going strong by giving workers a fair shot, provide more training and apprenticeships, hire them based on their skills not degrees. \n\nLet’s pass the Paycheck Fairness Act and paid leave. \n\nRaise the minimum wage to $15 an hour and extend the Child Tax Credit, so no one has to raise a family in poverty. \n\nLet’s increase Pell Grants and increase our historic support of HBCUs, and invest in what Jill—our First Lady who teaches full-time—calls America’s best-kept secret: community colleges. \n\nAnd let’s pass the PRO Act when a majority of workers want to form a union—they shouldn’t be stopped. \n\nWhen we invest in our workers, when we build the economy from the bottom up and the middle out together, we can do something we haven’t done in a long time: build a better America. \n\nFor more than two years, COVID-19 has impacted every decision in our lives and the life of the nation. \n\nAnd I know you’re tired, frustrated, and exhausted. \n\nBut I also know this. \n\nBecause of the progress we’ve made, because of your resilience and the tools we have, tonight I can say \nwe are moving forward safely, back to more normal routines. \n\nWe’ve reached a new moment in the fight against COVID-19, with severe cases down to a level not seen since last July. \n\nJust a few days ago, the Centers for Disease Control and Prevention—the CDC—issued new mask guidelines. \n\nUnder these new guidelines, most Americans in most of the country can now be mask free. \n\nAnd based on the projections, more of the country will reach that point across the next couple of weeks. \n\nThanks to the progress we have made this past year, COVID-19 need no longer control our lives. \n\nI know some are talking about “living with COVID-19”. Tonight – I say that we will never just accept living with COVID-19. \n\nWe will continue to combat the virus as we do other diseases. And because this is a virus that mutates and spreads, we will stay on guard. \n\nHere are four common sense steps as we move forward safely. \n\nFirst, stay protected with vaccines and treatments. We know how incredibly effective vaccines are. If you’re vaccinated and boosted you have the highest degree of protection. \n\nWe will never give up on vaccinating more Americans. Now, I know parents with kids under 5 are eager to see a vaccine authorized for their children. \n\nThe scientists are working hard to get that done and we’ll be ready with plenty of vaccines when they do. \n\nWe’re also ready with anti-viral treatments. If you get COVID-19, the Pfizer pill reduces your chances of ending up in the hospital by 90%. \n\nWe’ve ordered more of these pills than anyone in the world. And Pfizer is working overtime to get us 1 Million pills this month and more than double that next month. \n\nAnd we’re launching the “Test to Treat” initiative so people can get tested at a pharmacy, and if they’re positive, receive antiviral pills on the spot at no cost. \n\nIf you’re immunocompromised or have some other vulnerability, we have treatments and free high-quality masks. \n\nWe’re leaving no one behind or ignoring anyone’s needs as we move forward. \n\nAnd on testing, we have made hundreds of millions of tests available for you to order for free. \n\nEven if you already ordered free tests tonight, I am announcing that you can order more from covidtests.gov starting next week. \n\nSecond – we must prepare for new variants. Over the past year, we’ve gotten much better at detecting new variants. \n\nIf necessary, we’ll be able to deploy new vaccines within 100 days instead of many more months or years. \n\nAnd, if Congress provides the funds we need, we’ll have new stockpiles of tests, masks, and pills ready if needed. \n\nI cannot promise a new variant won’t come. But I can promise you we’ll do everything within our power to be ready if it does. \n\nThird – we can end the shutdown of schools and businesses. We have the tools we need. \n\nIt’s time for Americans to get back to work and fill our great downtowns again. People working from home can feel safe to begin to return to the office. \n\nWe’re doing that here in the federal government. The vast majority of federal workers will once again work in person. \n\nOur schools are open. Let’s keep it that way. Our kids need to be in school. \n\nAnd with 75% of adult Americans fully vaccinated and hospitalizations down by 77%, most Americans can remove their masks, return to work, stay in the classroom, and move forward safely. \n\nWe achieved this because we provided free vaccines, treatments, tests, and masks. \n\nOf course, continuing this costs money. \n\nI will soon send Congress a request. \n\nThe vast majority of Americans have used these tools and may want to again, so I expect Congress to pass it quickly. \n\nFourth, we will continue vaccinating the world. \n\nWe’ve sent 475 Million vaccine doses to 112 countries, more than any other nation. \n\nAnd we won’t stop. \n\nWe have lost so much to COVID-19. Time with one another. And worst of all, so much loss of life. \n\nLet’s use this moment to reset. Let’s stop looking at COVID-19 as a partisan dividing line and see it for what it is: A God-awful disease. \n\nLet’s stop seeing each other as enemies, and start seeing each other for who we really are: Fellow Americans. \n\nWe can’t change how divided we’ve been. But we can change how we move forward—on COVID-19 and other issues we must face together. \n\nI recently visited the New York City Police Department days after the funerals of Officer Wilbert Mora and his partner, Officer Jason Rivera. \n\nThey were responding to a 9-1-1 call when a man shot and killed them with a stolen gun. \n\nOfficer Mora was 27 years old. \n\nOfficer Rivera was 22. \n\nBoth Dominican Americans who’d grown up on the same streets they later chose to patrol as police officers. \n\nI spoke with their families and told them that we are forever in debt for their sacrifice, and we will carry on their mission to restore the trust and safety every community deserves. \n\nI’ve worked on these issues a long time. \n\nI know what works: Investing in crime preventionand community police officers who’ll walk the beat, who’ll know the neighborhood, and who can restore trust and safety. \n\nSo let’s not abandon our streets. Or choose between safety and equal justice. \n\nLet’s come together to protect our communities, restore trust, and hold law enforcement accountable. \n\nThat’s why the Justice Department required body cameras, banned chokeholds, and restricted no-knock warrants for its officers. \n\nThat’s why the American Rescue Plan provided $350 Billion that cities, states, and counties can use to hire more police and invest in proven strategies like community violence interruption—trusted messengers breaking the cycle of violence and trauma and giving young people hope. \n\nWe should all agree: The answer is not to Defund the police. The answer is to FUND the police with the resources and training they need to protect our communities. \n\nI ask Democrats and Republicans alike: Pass my budget and keep our neighborhoods safe. \n\nAnd I will keep doing everything in my power to crack down on gun trafficking and ghost guns you can buy online and make at home—they have no serial numbers and can’t be traced. \n\nAnd I ask Congress to pass proven measures to reduce gun violence. Pass universal background checks. Why should anyone on a terrorist list be able to purchase a weapon? \n\nBan assault weapons and high-capacity magazines. \n\nRepeal the liability shield that makes gun manufacturers the only industry in America that can’t be sued. \n\nThese laws don’t infringe on the Second Amendment. They save lives. \n\nThe most fundamental right in America is the right to vote – and to have it counted. And it’s under assault. \n\nIn state after state, new laws have been passed, not only to suppress the vote, but to subvert entire elections. \n\nWe cannot let this happen. \n\nTonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you’re at it, pass the Disclose Act so Americans can know who is funding our elections. \n\nTonight, I’d like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service. \n\nOne of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court. \n\nAnd I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation’s top legal minds, who will continue Justice Breyer’s legacy of excellence. \n\nA former top litigator in private practice. A former federal public defender. And from a family of public school educators and police officers. A consensus builder. Since she’s been nominated, she’s received a broad range of support—from the Fraternal Order of Police to former judges appointed by Democrats and Republicans. \n\nAnd if we are to advance liberty and justice, we need to secure the Border and fix the immigration system. \n\nWe can do both. At our border, we’ve installed new technology like cutting-edge scanners to better detect drug smuggling. \n\nWe’ve set up joint patrols with Mexico and Guatemala to catch more human traffickers. \n\nWe’re putting in place dedicated immigration judges so families fleeing persecution and violence can have their cases heard faster. \n\nWe’re securing commitments and supporting partners in South and Central America to host more refugees and secure their own borders. \n\nWe can do all this while keeping lit the torch of liberty that has led generations of immigrants to this land—my forefathers and so many of yours. \n\nProvide a pathway to citizenship for Dreamers, those on temporary status, farm workers, and essential workers. \n\nRevise our laws so businesses have the workers they need and families don’t wait decades to reunite. \n\nIt’s not only the right thing to do—it’s the economically smart thing to do. \n\nThat’s why immigration reform is supported by everyone from labor unions to religious leaders to the U.S. Chamber of Commerce. \n\nLet’s get it done once and for all. \n\nAdvancing liberty and justice also requires protecting the rights of women. \n\nThe constitutional right affirmed in Roe v. Wade—standing precedent for half a century—is under attack as never before. \n\nIf we want to go forward—not backward—we must protect access to health care. Preserve a woman’s right to choose. And let’s continue to advance maternal health care in America. \n\nAnd for our LGBTQ+ Americans, let’s finally get the bipartisan Equality Act to my desk. The onslaught of state laws targeting transgender Americans and their families is wrong. \n\nAs I said last year, especially to our younger transgender Americans, I will always have your back as your President, so you can be yourself and reach your God-given potential. \n\nWhile it often appears that we never agree, that isn’t true. I signed 80 bipartisan bills into law last year. From preventing government shutdowns to protecting Asian-Americans from still-too-common hate crimes to reforming military justice. \n\nAnd soon, we’ll strengthen the Violence Against Women Act that I first wrote three decades ago. It is important for us to show the nation that we can come together and do big things. \n\nSo tonight I’m offering a Unity Agenda for the Nation. Four big things we can do together. \n\nFirst, beat the opioid epidemic. \n\nThere is so much we can do. Increase funding for prevention, treatment, harm reduction, and recovery. \n\nGet rid of outdated rules that stop doctors from prescribing treatments. And stop the flow of illicit drugs by working with state and local law enforcement to go after traffickers. \n\nIf you’re suffering from addiction, know you are not alone. I believe in recovery, and I celebrate the 23 million Americans in recovery. \n\nSecond, let’s take on mental health. Especially among our children, whose lives and education have been turned upside down. \n\nThe American Rescue Plan gave schools money to hire teachers and help students make up for lost learning. \n\nI urge every parent to make sure your school does just that. And we can all play a part—sign up to be a tutor or a mentor. \n\nChildren were also struggling before the pandemic. Bullying, violence, trauma, and the harms of social media. \n\nAs Frances Haugen, who is here with us tonight, has shown, we must hold social media platforms accountable for the national experiment they’re conducting on our children for profit. \n\nIt’s time to strengthen privacy protections, ban targeted advertising to children, demand tech companies stop collecting personal data on our children. \n\nAnd let’s get all Americans the mental health services they need. More people they can turn to for help, and full parity between physical and mental health care. \n\nThird, support our veterans. \n\nVeterans are the best of us. \n\nI’ve always believed that we have a sacred obligation to equip all those we send to war and care for them and their families when they come home. \n\nMy administration is providing assistance with job training and housing, and now helping lower-income veterans get VA care debt-free. \n\nOur troops in Iraq and Afghanistan faced many dangers. \n\nOne was stationed at bases and breathing in toxic smoke from “burn pits” that incinerated wastes of war—medical and hazard material, jet fuel, and more. \n\nWhen they came home, many of the world’s fittest and best trained warriors were never the same. \n\nHeadaches. Numbness. Dizziness. \n\nA cancer that would put them in a flag-draped coffin. \n\nI know. \n\nOne of those soldiers was my son Major Beau Biden. \n\nWe don’t know for sure if a burn pit was the cause of his brain cancer, or the diseases of so many of our troops. \n\nBut I’m committed to finding out everything we can. \n\nCommitted to military families like Danielle Robinson from Ohio. \n\nThe widow of Sergeant First Class Heath Robinson. \n\nHe was born a soldier. Army National Guard. Combat medic in Kosovo and Iraq. \n\nStationed near Baghdad, just yards from burn pits the size of football fields. \n\nHeath’s widow Danielle is here with us tonight. They loved going to Ohio State football games. He loved building Legos with their daughter. \n\nBut cancer from prolonged exposure to burn pits ravaged Heath’s lungs and body. \n\nDanielle says Heath was a fighter to the very end. \n\nHe didn’t know how to stop fighting, and neither did she. \n\nThrough her pain she found purpose to demand we do better. \n\nTonight, Danielle—we are. \n\nThe VA is pioneering new ways of linking toxic exposures to diseases, already helping more veterans get benefits. \n\nAnd tonight, I’m announcing we’re expanding eligibility to veterans suffering from nine respiratory cancers. \n\nI’m also calling on Congress: pass a law to make sure veterans devastated by toxic exposures in Iraq and Afghanistan finally get the benefits and comprehensive health care they deserve. \n\nAnd fourth, let’s end cancer as we know it. \n\nThis is personal to me and Jill, to Kamala, and to so many of you. \n\nCancer is the #2 cause of death in America–second only to heart disease. \n\nLast month, I announced our plan to supercharge \nthe Cancer Moonshot that President Obama asked me to lead six years ago. \n\nOur goal is to cut the cancer death rate by at least 50% over the next 25 years, turn more cancers from death sentences into treatable diseases. \n\nMore support for patients and families. \n\nTo get there, I call on Congress to fund ARPA-H, the Advanced Research Projects Agency for Health. \n\nIt’s based on DARPA—the Defense Department project that led to the Internet, GPS, and so much more. \n\nARPA-H will have a singular purpose—to drive breakthroughs in cancer, Alzheimer’s, diabetes, and more. \n\nA unity agenda for the nation. \n\nWe can do this. \n\nMy fellow Americans—tonight , we have gathered in a sacred space—the citadel of our democracy. \n\nIn this Capitol, generation after generation, Americans have debated great questions amid great strife, and have done great things. \n\nWe have fought for freedom, expanded liberty, defeated totalitarianism and terror. \n\nAnd built the strongest, freest, and most prosperous nation the world has ever known. \n\nNow is the hour. \n\nOur moment of responsibility. \n\nOur test of resolve and conscience, of history itself. \n\nIt is in this moment that our character is formed. Our purpose is found. Our future is forged. \n\nWell I know this nation. \n\nWe will meet the test. \n\nTo protect freedom and liberty, to expand fairness and opportunity. \n\nWe will save democracy. \n\nAs hard as these times have been, I am more optimistic about America today than I have been my whole life. \n\nBecause I see the future that is within our grasp. \n\nBecause I know there is simply nothing beyond our capacity. \n\nWe are the only nation on Earth that has always turned every crisis we have faced into an opportunity. \n\nThe only nation that can be defined by a single word: possibilities. \n\nSo on this night, in our 245th year as a nation, I have come to report on the State of the Union. \n\nAnd my report is this: the State of the Union is strong—because you, the American people, are strong. \n\nWe are stronger today than we were a year ago. \n\nAnd we will be stronger a year from now than we are today. \n\nNow is our moment to meet and overcome the challenges of our time. \n\nAnd we will, as one people. \n\nOne America. \n\nThe United States of America. \n\nMay God bless you all. May God protect our troops.", - "textSplitter": "{{recursiveCharacterTextSplitter_0.data.instance}}", - "metadata": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "plainText_1-output-document-Document|json", - "name": "document", - "label": "Document", - "type": "Document | json" - }, - { - "id": "plainText_1-output-text-string|json", - "name": "text", - "label": "Text", - "type": "string | json" - } - ], - "default": "document" - } - ], - "outputs": { - "output": "document" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 117.23894449422778, - "y": 23.24339894687961 - }, - "dragging": false - }, - { - "width": 300, - "height": 430, - "id": "recursiveCharacterTextSplitter_0", - "position": { - "x": -259.38954307457425, - "y": 75.96855802341503 - }, - "type": "customNode", - "data": { - "id": "recursiveCharacterTextSplitter_0", - "label": "Recursive Character Text Splitter", - "version": 2, - "name": "recursiveCharacterTextSplitter", - "type": "RecursiveCharacterTextSplitter", - "baseClasses": ["RecursiveCharacterTextSplitter", "TextSplitter", "BaseDocumentTransformer", "Runnable"], - "category": "Text Splitters", - "description": "Split documents recursively by different characters - starting with \"\\n\\n\", then \"\\n\", then \" \"", - "inputParams": [ - { - "label": "Chunk Size", - "name": "chunkSize", - "type": "number", - "default": 1000, - "optional": true, - "id": "recursiveCharacterTextSplitter_0-input-chunkSize-number" - }, - { - "label": "Chunk Overlap", - "name": "chunkOverlap", - "type": "number", - "optional": true, - "id": "recursiveCharacterTextSplitter_0-input-chunkOverlap-number" - }, - { - "label": "Custom Separators", - "name": "separators", - "type": "string", - "rows": 4, - "description": "Array of custom separators to determine when to split the text, will override the default separators", - "placeholder": "[\"|\", \"##\", \">\", \"-\"]", - "additionalParams": true, - "optional": true, - "id": "recursiveCharacterTextSplitter_0-input-separators-string" - } - ], - "inputAnchors": [], - "inputs": { - "chunkSize": 1000, - "chunkOverlap": "", - "separators": "" - }, - "outputAnchors": [ - { - "id": "recursiveCharacterTextSplitter_0-output-recursiveCharacterTextSplitter-RecursiveCharacterTextSplitter|TextSplitter|BaseDocumentTransformer|Runnable", - "name": "recursiveCharacterTextSplitter", - "label": "RecursiveCharacterTextSplitter", - "type": "RecursiveCharacterTextSplitter | TextSplitter | BaseDocumentTransformer | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": -259.38954307457425, - "y": 75.96855802341503 - }, - "dragging": false - }, - { - "width": 300, - "height": 435, - "id": "conversationalAgent_0", - "position": { - "x": 2432.125364763489, - "y": -105.27942167533908 - }, - "type": "customNode", - "data": { - "id": "conversationalAgent_0", - "label": "Conversational Agent", - "version": 3, - "name": "conversationalAgent", - "type": "AgentExecutor", - "baseClasses": ["AgentExecutor", "BaseChain", "Runnable"], - "category": "Agents", - "description": "Conversational agent for a chat model. It will utilize chat specific prompts", - "inputParams": [ - { - "label": "System Message", - "name": "systemMessage", - "type": "string", - "rows": 4, - "default": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist.", - "optional": true, - "additionalParams": true, - "id": "conversationalAgent_0-input-systemMessage-string" - }, - { - "label": "Max Iterations", - "name": "maxIterations", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "conversationalAgent_0-input-maxIterations-number" - } - ], - "inputAnchors": [ - { - "label": "Allowed Tools", - "name": "tools", - "type": "Tool", - "list": true, - "id": "conversationalAgent_0-input-tools-Tool" - }, - { - "label": "Chat Model", - "name": "model", - "type": "BaseChatModel", - "id": "conversationalAgent_0-input-model-BaseChatModel" - }, - { - "label": "Memory", - "name": "memory", - "type": "BaseChatMemory", - "id": "conversationalAgent_0-input-memory-BaseChatMemory" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "conversationalAgent_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "inputModeration": "", - "tools": ["{{chainTool_2.data.instance}}", "{{chainTool_3.data.instance}}"], - "model": "{{chatOllama_0.data.instance}}", - "memory": "{{bufferMemory_0.data.instance}}", - "systemMessage": "Assistant is a large language model trained by OpenAI.\n\nAssistant is designed to be able to assist with a wide range of tasks, from answering simple questions to providing in-depth explanations and discussions on a wide range of topics. As a language model, Assistant is able to generate human-like text based on the input it receives, allowing it to engage in natural-sounding conversations and provide responses that are coherent and relevant to the topic at hand.\n\nAssistant is constantly learning and improving, and its capabilities are constantly evolving. It is able to process and understand large amounts of text, and can use this knowledge to provide accurate and informative responses to a wide range of questions. Additionally, Assistant is able to generate its own text based on the input it receives, allowing it to engage in discussions and provide explanations and descriptions on a wide range of topics.\n\nOverall, Assistant is a powerful system that can help with a wide range of tasks and provide valuable insights and information on a wide range of topics. Whether you need help with a specific question or just want to have a conversation about a particular topic, Assistant is here to assist." - }, - "outputAnchors": [ - { - "id": "conversationalAgent_0-output-conversationalAgent-AgentExecutor|BaseChain|Runnable", - "name": "conversationalAgent", - "label": "AgentExecutor", - "type": "AgentExecutor | BaseChain | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 2432.125364763489, - "y": -105.27942167533908 - }, - "dragging": false - }, - { - "id": "chatOllama_0", - "position": { - "x": 1662.4375746412504, - "y": 114.83248283616422 - }, - "type": "customNode", - "data": { - "id": "chatOllama_0", - "label": "ChatOllama", - "version": 2, - "name": "chatOllama", - "type": "ChatOllama", - "baseClasses": ["ChatOllama", "SimpleChatModel", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Chat completion using open-source LLM on Ollama", - "inputParams": [ - { - "label": "Base URL", - "name": "baseUrl", - "type": "string", - "default": "http://localhost:11434", - "id": "chatOllama_0-input-baseUrl-string" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "string", - "placeholder": "llama2", - "id": "chatOllama_0-input-modelName-string" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "description": "The temperature of the model. Increasing the temperature will make the model answer more creatively. (Default: 0.8). Refer to docs for more details", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOllama_0-input-temperature-number" - }, - { - "label": "Top P", - "name": "topP", - "type": "number", - "description": "Works together with top-k. A higher value (e.g., 0.95) will lead to more diverse text, while a lower value (e.g., 0.5) will generate more focused and conservative text. (Default: 0.9). Refer to docs for more details", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-topP-number" - }, - { - "label": "Top K", - "name": "topK", - "type": "number", - "description": "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40). Refer to docs for more details", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-topK-number" - }, - { - "label": "Mirostat", - "name": "mirostat", - "type": "number", - "description": "Enable Mirostat sampling for controlling perplexity. (default: 0, 0 = disabled, 1 = Mirostat, 2 = Mirostat 2.0). Refer to docs for more details", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-mirostat-number" - }, - { - "label": "Mirostat ETA", - "name": "mirostatEta", - "type": "number", - "description": "Influences how quickly the algorithm responds to feedback from the generated text. A lower learning rate will result in slower adjustments, while a higher learning rate will make the algorithm more responsive. (Default: 0.1) Refer to docs for more details", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-mirostatEta-number" - }, - { - "label": "Mirostat TAU", - "name": "mirostatTau", - "type": "number", - "description": "Controls the balance between coherence and diversity of the output. A lower value will result in more focused and coherent text. (Default: 5.0) Refer to docs for more details", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-mirostatTau-number" - }, - { - "label": "Context Window Size", - "name": "numCtx", - "type": "number", - "description": "Sets the size of the context window used to generate the next token. (Default: 2048) Refer to docs for more details", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-numCtx-number" - }, - { - "label": "Number of GQA groups", - "name": "numGqa", - "type": "number", - "description": "The number of GQA groups in the transformer layer. Required for some models, for example it is 8 for llama2:70b. Refer to docs for more details", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-numGqa-number" - }, - { - "label": "Number of GPU", - "name": "numGpu", - "type": "number", - "description": "The number of layers to send to the GPU(s). On macOS it defaults to 1 to enable metal support, 0 to disable. Refer to docs for more details", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-numGpu-number" - }, - { - "label": "Number of Thread", - "name": "numThread", - "type": "number", - "description": "Sets the number of threads to use during computation. By default, Ollama will detect this for optimal performance. It is recommended to set this value to the number of physical CPU cores your system has (as opposed to the logical number of cores). Refer to docs for more details", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-numThread-number" - }, - { - "label": "Repeat Last N", - "name": "repeatLastN", - "type": "number", - "description": "Sets how far back for the model to look back to prevent repetition. (Default: 64, 0 = disabled, -1 = num_ctx). Refer to docs for more details", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-repeatLastN-number" - }, - { - "label": "Repeat Penalty", - "name": "repeatPenalty", - "type": "number", - "description": "Sets how strongly to penalize repetitions. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 0.9) will be more lenient. (Default: 1.1). Refer to docs for more details", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-repeatPenalty-number" - }, - { - "label": "Stop Sequence", - "name": "stop", - "type": "string", - "rows": 4, - "placeholder": "AI assistant:", - "description": "Sets the stop sequences to use. Use comma to seperate different sequences. Refer to docs for more details", - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-stop-string" - }, - { - "label": "Tail Free Sampling", - "name": "tfsZ", - "type": "number", - "description": "Tail free sampling is used to reduce the impact of less probable tokens from the output. A higher value (e.g., 2.0) will reduce the impact more, while a value of 1.0 disables this setting. (Default: 1). Refer to docs for more details", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOllama_0-input-tfsZ-number" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOllama_0-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "baseUrl": "http://localhost:11434", - "modelName": "llama2", - "temperature": 0.9, - "topP": "", - "topK": "", - "mirostat": "", - "mirostatEta": "", - "mirostatTau": "", - "numCtx": "", - "numGqa": "", - "numGpu": "", - "numThread": "", - "repeatLastN": "", - "repeatPenalty": "", - "stop": "", - "tfsZ": "" - }, - "outputAnchors": [ - { - "id": "chatOllama_0-output-chatOllama-ChatOllama|SimpleChatModel|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOllama", - "label": "ChatOllama", - "description": "Chat completion using open-source LLM on Ollama", - "type": "ChatOllama | SimpleChatModel | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 580, - "selected": false, - "positionAbsolute": { - "x": 1662.4375746412504, - "y": 114.83248283616422 - }, - "dragging": false - }, - { - "id": "stickyNote_0", - "position": { - "x": 2421.3310049814813, - "y": -395.88989972468414 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_0", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_0-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Conversational Agent is suitable for LLM which doesn't have function calling support.\n\nIt uses the prompt to decide which Chain Tool is appropriate to answer user question. Downside is there could be higher error rate due to hallucination.\n\nOtherwise, it is recommended to use Multiple Documents QnA template which uses Tool Agent" - }, - "outputAnchors": [ - { - "id": "stickyNote_0-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 264, - "selected": false, - "positionAbsolute": { - "x": 2421.3310049814813, - "y": -395.88989972468414 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "retrievalQAChain_0", - "sourceHandle": "retrievalQAChain_0-output-retrievalQAChain-RetrievalQAChain|BaseChain|BaseLangChain", - "target": "chainTool_2", - "targetHandle": "chainTool_2-input-baseChain-BaseChain", - "type": "buttonedge", - "id": "retrievalQAChain_0-retrievalQAChain_0-output-retrievalQAChain-RetrievalQAChain|BaseChain|BaseLangChain-chainTool_2-chainTool_2-input-baseChain-BaseChain", - "data": { - "label": "" - } - }, - { - "source": "retrievalQAChain_1", - "sourceHandle": "retrievalQAChain_1-output-retrievalQAChain-RetrievalQAChain|BaseChain|BaseLangChain", - "target": "chainTool_3", - "targetHandle": "chainTool_3-input-baseChain-BaseChain", - "type": "buttonedge", - "id": "retrievalQAChain_1-retrievalQAChain_1-output-retrievalQAChain-RetrievalQAChain|BaseChain|BaseLangChain-chainTool_3-chainTool_3-input-baseChain-BaseChain", - "data": { - "label": "" - } - }, - { - "source": "openAIEmbeddings_1", - "sourceHandle": "openAIEmbeddings_1-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "target": "redis_0", - "targetHandle": "redis_0-input-embeddings-Embeddings", - "type": "buttonedge", - "id": "openAIEmbeddings_1-openAIEmbeddings_1-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings-redis_0-redis_0-input-embeddings-Embeddings", - "data": { - "label": "" - } - }, - { - "source": "redis_0", - "sourceHandle": "redis_0-output-retriever-Redis|VectorStoreRetriever|BaseRetriever", - "target": "retrievalQAChain_0", - "targetHandle": "retrievalQAChain_0-input-vectorStoreRetriever-BaseRetriever", - "type": "buttonedge", - "id": "redis_0-redis_0-output-retriever-Redis|VectorStoreRetriever|BaseRetriever-retrievalQAChain_0-retrievalQAChain_0-input-vectorStoreRetriever-BaseRetriever", - "data": { - "label": "" - } - }, - { - "source": "plainText_0", - "sourceHandle": "plainText_0-output-document-Document|json", - "target": "redis_0", - "targetHandle": "redis_0-input-document-Document", - "type": "buttonedge", - "id": "plainText_0-plainText_0-output-document-Document|json-redis_0-redis_0-input-document-Document", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_0", - "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "retrievalQAChain_0", - "targetHandle": "retrievalQAChain_0-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-retrievalQAChain_0-retrievalQAChain_0-input-model-BaseLanguageModel", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_1", - "sourceHandle": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "retrievalQAChain_1", - "targetHandle": "retrievalQAChain_1-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_1-chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-retrievalQAChain_1-retrievalQAChain_1-input-model-BaseLanguageModel", - "data": { - "label": "" - } - }, - { - "source": "faiss_0", - "sourceHandle": "faiss_0-output-retriever-Faiss|VectorStoreRetriever|BaseRetriever", - "target": "retrievalQAChain_1", - "targetHandle": "retrievalQAChain_1-input-vectorStoreRetriever-BaseRetriever", - "type": "buttonedge", - "id": "faiss_0-faiss_0-output-retriever-Faiss|VectorStoreRetriever|BaseRetriever-retrievalQAChain_1-retrievalQAChain_1-input-vectorStoreRetriever-BaseRetriever", - "data": { - "label": "" - } - }, - { - "source": "openAIEmbeddings_2", - "sourceHandle": "openAIEmbeddings_2-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "target": "faiss_0", - "targetHandle": "faiss_0-input-embeddings-Embeddings", - "type": "buttonedge", - "id": "openAIEmbeddings_2-openAIEmbeddings_2-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings-faiss_0-faiss_0-input-embeddings-Embeddings", - "data": { - "label": "" - } - }, - { - "source": "plainText_1", - "sourceHandle": "plainText_1-output-document-Document|json", - "target": "faiss_0", - "targetHandle": "faiss_0-input-document-Document", - "type": "buttonedge", - "id": "plainText_1-plainText_1-output-document-Document|json-faiss_0-faiss_0-input-document-Document", - "data": { - "label": "" - } - }, - { - "source": "recursiveCharacterTextSplitter_0", - "sourceHandle": "recursiveCharacterTextSplitter_0-output-recursiveCharacterTextSplitter-RecursiveCharacterTextSplitter|TextSplitter|BaseDocumentTransformer|Runnable", - "target": "plainText_1", - "targetHandle": "plainText_1-input-textSplitter-TextSplitter", - "type": "buttonedge", - "id": "recursiveCharacterTextSplitter_0-recursiveCharacterTextSplitter_0-output-recursiveCharacterTextSplitter-RecursiveCharacterTextSplitter|TextSplitter|BaseDocumentTransformer|Runnable-plainText_1-plainText_1-input-textSplitter-TextSplitter", - "data": { - "label": "" - } - }, - { - "source": "chainTool_2", - "sourceHandle": "chainTool_2-output-chainTool-ChainTool|DynamicTool|Tool|StructuredTool|BaseLangChain", - "target": "conversationalAgent_0", - "targetHandle": "conversationalAgent_0-input-tools-Tool", - "type": "buttonedge", - "id": "chainTool_2-chainTool_2-output-chainTool-ChainTool|DynamicTool|Tool|StructuredTool|BaseLangChain-conversationalAgent_0-conversationalAgent_0-input-tools-Tool", - "data": { - "label": "" - } - }, - { - "source": "chainTool_3", - "sourceHandle": "chainTool_3-output-chainTool-ChainTool|DynamicTool|Tool|StructuredTool|BaseLangChain", - "target": "conversationalAgent_0", - "targetHandle": "conversationalAgent_0-input-tools-Tool", - "type": "buttonedge", - "id": "chainTool_3-chainTool_3-output-chainTool-ChainTool|DynamicTool|Tool|StructuredTool|BaseLangChain-conversationalAgent_0-conversationalAgent_0-input-tools-Tool", - "data": { - "label": "" - } - }, - { - "source": "bufferMemory_0", - "sourceHandle": "bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory", - "target": "conversationalAgent_0", - "targetHandle": "conversationalAgent_0-input-memory-BaseChatMemory", - "type": "buttonedge", - "id": "bufferMemory_0-bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory-conversationalAgent_0-conversationalAgent_0-input-memory-BaseChatMemory", - "data": { - "label": "" - } - }, - { - "source": "chatOllama_0", - "sourceHandle": "chatOllama_0-output-chatOllama-ChatOllama|SimpleChatModel|BaseChatModel|BaseLanguageModel|Runnable", - "target": "conversationalAgent_0", - "targetHandle": "conversationalAgent_0-input-model-BaseChatModel", - "type": "buttonedge", - "id": "chatOllama_0-chatOllama_0-output-chatOllama-ChatOllama|SimpleChatModel|BaseChatModel|BaseLanguageModel|Runnable-conversationalAgent_0-conversationalAgent_0-input-model-BaseChatModel" - } - ] -} diff --git a/packages/server/marketplaces/chatflows/API Agent.json b/packages/server/marketplaces/chatflows/OpenAPI YAML Agent.json similarity index 99% rename from packages/server/marketplaces/chatflows/API Agent.json rename to packages/server/marketplaces/chatflows/OpenAPI YAML Agent.json index 5d3084be..5e958da7 100644 --- a/packages/server/marketplaces/chatflows/API Agent.json +++ b/packages/server/marketplaces/chatflows/OpenAPI YAML Agent.json @@ -1,5 +1,5 @@ { - "description": "Given API docs, agent automatically decide which API to call, generating url and body request from conversation", + "description": "Given an OpenAPI YAML file, agent automatically decide which API to call, generating url and body request from conversation", "framework": ["Langchain"], "usecases": ["Interacting with API"], "nodes": [ diff --git a/packages/server/marketplaces/chatflows/Prompt Chaining with VectorStore.json b/packages/server/marketplaces/chatflows/Prompt Chaining with VectorStore.json deleted file mode 100644 index 881106fc..00000000 --- a/packages/server/marketplaces/chatflows/Prompt Chaining with VectorStore.json +++ /dev/null @@ -1,1277 +0,0 @@ -{ - "description": "Use chat history to rephrase user question, then answer the rephrased question using retrieved docs from vector store", - "usecases": ["Documents QnA"], - "framework": ["Langchain"], - "nodes": [ - { - "width": 300, - "height": 511, - "id": "promptTemplate_0", - "position": { - "x": 344.73370692733414, - "y": -122.34815000085804 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_0", - "label": "Prompt Template", - "version": 1, - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate", "Runnable"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_0-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_0-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "template": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.\n\nChat History:\n{chat_history}\nFollow Up Input: {question}\nStandalone question:", - "promptValues": "{\"question\":\"{{question}}\",\"chat_history\":\"{{chat_history}}\"}" - }, - "outputAnchors": [ - { - "id": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 344.73370692733414, - "y": -122.34815000085804 - }, - "dragging": false - }, - { - "width": 300, - "height": 688, - "id": "chatPromptTemplate_0", - "position": { - "x": 2314.8876045231254, - "y": -163.68061503572068 - }, - "type": "customNode", - "data": { - "id": "chatPromptTemplate_0", - "label": "Chat Prompt Template", - "version": 1, - "name": "chatPromptTemplate", - "type": "ChatPromptTemplate", - "baseClasses": ["ChatPromptTemplate", "BaseChatPromptTemplate", "BasePromptTemplate", "Runnable"], - "category": "Prompts", - "description": "Schema to represent a chat prompt", - "inputParams": [ - { - "label": "System Message", - "name": "systemMessagePrompt", - "type": "string", - "rows": 4, - "placeholder": "You are a helpful assistant that translates {input_language} to {output_language}.", - "id": "chatPromptTemplate_0-input-systemMessagePrompt-string" - }, - { - "label": "Human Message", - "name": "humanMessagePrompt", - "type": "string", - "rows": 4, - "placeholder": "{text}", - "id": "chatPromptTemplate_0-input-humanMessagePrompt-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "chatPromptTemplate_0-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "systemMessagePrompt": "Using the provided context, answer the user's question to the best of your ability using the resources provided. If there is nothing in the context relevant to the question at hand, just say \"Hmm, I'm not sure.\" Don't try to make up an answer.\n\nAnything between the following \\`context\\` html blocks is retrieved from a knowledge bank, not part of the conversation with the user.\n\n\n {context}\n\n\nREMEMBER: If there is no relevant information within the context, just say \"Hmm, I'm not sure.\" Don't try to make up an answer. Anything between the preceding 'context' html blocks is retrieved from a knowledge bank, not part of the conversation with the user.", - "humanMessagePrompt": "{text}", - "promptValues": "{\"context\":\"{{vectorStoreToDocument_0.data.instance}}\",\"text\":\"{{question}}\"}" - }, - "outputAnchors": [ - { - "id": "chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate|Runnable", - "name": "chatPromptTemplate", - "label": "ChatPromptTemplate", - "type": "ChatPromptTemplate | BaseChatPromptTemplate | BasePromptTemplate | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 2314.8876045231254, - "y": -163.68061503572068 - }, - "dragging": false - }, - { - "width": 300, - "height": 454, - "id": "vectorStoreToDocument_0", - "position": { - "x": 1906.6871314089658, - "y": -157.0046189166955 - }, - "type": "customNode", - "data": { - "id": "vectorStoreToDocument_0", - "label": "VectorStore To Document", - "version": 2, - "name": "vectorStoreToDocument", - "type": "Document", - "baseClasses": ["Document"], - "category": "Document Loaders", - "description": "Search documents with scores from vector store", - "inputParams": [ - { - "label": "Query", - "name": "query", - "type": "string", - "description": "Query to retrieve documents from vector database. If not specified, user question will be used", - "optional": true, - "acceptVariable": true, - "id": "vectorStoreToDocument_0-input-query-string" - }, - { - "label": "Minimum Score (%)", - "name": "minScore", - "type": "number", - "optional": true, - "placeholder": "75", - "step": 1, - "description": "Minumum score for embeddings documents to be included", - "id": "vectorStoreToDocument_0-input-minScore-number" - } - ], - "inputAnchors": [ - { - "label": "Vector Store", - "name": "vectorStore", - "type": "VectorStore", - "id": "vectorStoreToDocument_0-input-vectorStore-VectorStore" - } - ], - "inputs": { - "vectorStore": "{{singlestore_0.data.instance}}", - "query": "{{llmChain_2.data.instance}}", - "minScore": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "vectorStoreToDocument_0-output-document-Document|json", - "name": "document", - "label": "Document", - "type": "Document | json" - }, - { - "id": "vectorStoreToDocument_0-output-text-string|json", - "name": "text", - "label": "Text", - "type": "string | json" - } - ], - "default": "document" - } - ], - "outputs": { - "output": "text" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1906.6871314089658, - "y": -157.0046189166955 - }, - "dragging": false - }, - { - "width": 300, - "height": 507, - "id": "llmChain_2", - "position": { - "x": 756.2678342825631, - "y": -244.07972550448233 - }, - "type": "customNode", - "data": { - "id": "llmChain_2", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_2-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_2-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_2-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_2-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_2-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatOpenAI_0.data.instance}}", - "prompt": "{{promptTemplate_0.data.instance}}", - "outputParser": "", - "chainName": "RephraseQuestion", - "inputModeration": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_2-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_2-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "outputPrediction" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 756.2678342825631, - "y": -244.07972550448233 - }, - "dragging": false - }, - { - "width": 300, - "height": 507, - "id": "llmChain_1", - "position": { - "x": 2716.1571046184436, - "y": -279.02657697343375 - }, - "type": "customNode", - "data": { - "id": "llmChain_1", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_1-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_1-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_1-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_1-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_1-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatOpenAI_1.data.instance}}", - "prompt": "{{chatPromptTemplate_0.data.instance}}", - "outputParser": "", - "chainName": "FinalResponse", - "inputModeration": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_1-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_1-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "llmChain" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 2716.1571046184436, - "y": -279.02657697343375 - }, - "dragging": false - }, - { - "width": 300, - "height": 669, - "id": "chatOpenAI_0", - "position": { - "x": 344.77878441903204, - "y": -832.2188929689953 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_0", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_0-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_0-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_0-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_0-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo-16k", - "temperature": "0", - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 344.77878441903204, - "y": -832.2188929689953 - }, - "dragging": false - }, - { - "width": 300, - "height": 669, - "id": "chatOpenAI_1", - "position": { - "x": 2296.3207911691625, - "y": -880.514745028577 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_1", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_1-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_1-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_1-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_1-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_1-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_1-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo-16k", - "temperature": "0", - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 2296.3207911691625, - "y": -880.514745028577 - }, - "dragging": false - }, - { - "width": 300, - "height": 652, - "id": "singlestore_0", - "position": { - "x": 1530.532503048084, - "y": -657.3586990397077 - }, - "type": "customNode", - "data": { - "id": "singlestore_0", - "label": "SingleStore", - "version": 1, - "name": "singlestore", - "type": "SingleStore", - "baseClasses": ["SingleStore", "VectorStoreRetriever", "BaseRetriever"], - "category": "Vector Stores", - "description": "Upsert embedded data and perform similarity search upon query using SingleStore, a fast and distributed cloud relational database", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "description": "Needed when using SingleStore cloud hosted", - "optional": true, - "credentialNames": ["singleStoreApi"], - "id": "singlestore_0-input-credential-credential" - }, - { - "label": "Host", - "name": "host", - "type": "string", - "id": "singlestore_0-input-host-string" - }, - { - "label": "Database", - "name": "database", - "type": "string", - "id": "singlestore_0-input-database-string" - }, - { - "label": "Table Name", - "name": "tableName", - "type": "string", - "placeholder": "embeddings", - "additionalParams": true, - "optional": true, - "id": "singlestore_0-input-tableName-string" - }, - { - "label": "Content Column Name", - "name": "contentColumnName", - "type": "string", - "placeholder": "content", - "additionalParams": true, - "optional": true, - "id": "singlestore_0-input-contentColumnName-string" - }, - { - "label": "Vector Column Name", - "name": "vectorColumnName", - "type": "string", - "placeholder": "vector", - "additionalParams": true, - "optional": true, - "id": "singlestore_0-input-vectorColumnName-string" - }, - { - "label": "Metadata Column Name", - "name": "metadataColumnName", - "type": "string", - "placeholder": "metadata", - "additionalParams": true, - "optional": true, - "id": "singlestore_0-input-metadataColumnName-string" - }, - { - "label": "Top K", - "name": "topK", - "placeholder": "4", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "singlestore_0-input-topK-number" - } - ], - "inputAnchors": [ - { - "label": "Document", - "name": "document", - "type": "Document", - "list": true, - "optional": true, - "id": "singlestore_0-input-document-Document" - }, - { - "label": "Embeddings", - "name": "embeddings", - "type": "Embeddings", - "id": "singlestore_0-input-embeddings-Embeddings" - } - ], - "inputs": { - "document": "", - "embeddings": "{{openAIEmbeddings_0.data.instance}}", - "host": "", - "database": "", - "tableName": "", - "contentColumnName": "", - "vectorColumnName": "", - "metadataColumnName": "", - "topK": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "singlestore_0-output-retriever-SingleStore|VectorStoreRetriever|BaseRetriever", - "name": "retriever", - "label": "SingleStore Retriever", - "type": "SingleStore | VectorStoreRetriever | BaseRetriever" - }, - { - "id": "singlestore_0-output-vectorStore-SingleStore|VectorStore", - "name": "vectorStore", - "label": "SingleStore Vector Store", - "type": "SingleStore | VectorStore" - } - ], - "default": "retriever" - } - ], - "outputs": { - "output": "vectorStore" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1530.532503048084, - "y": -657.3586990397077 - }, - "dragging": false - }, - { - "width": 300, - "height": 423, - "id": "openAIEmbeddings_0", - "position": { - "x": 1154.293946350955, - "y": -589.6072684085893 - }, - "type": "customNode", - "data": { - "id": "openAIEmbeddings_0", - "label": "OpenAI Embeddings", - "version": 4, - "name": "openAIEmbeddings", - "type": "OpenAIEmbeddings", - "baseClasses": ["OpenAIEmbeddings", "Embeddings"], - "category": "Embeddings", - "description": "OpenAI API to generate embeddings for a given text", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "openAIEmbeddings_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "text-embedding-ada-002", - "id": "openAIEmbeddings_0-input-modelName-asyncOptions" - }, - { - "label": "Strip New Lines", - "name": "stripNewLines", - "type": "boolean", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-stripNewLines-boolean" - }, - { - "label": "Batch Size", - "name": "batchSize", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-batchSize-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-basepath-string" - }, - { - "label": "Dimensions", - "name": "dimensions", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-dimensions-number" - } - ], - "inputAnchors": [], - "inputs": { - "modelName": "text-embedding-ada-002", - "stripNewLines": "", - "batchSize": "", - "timeout": "", - "basepath": "", - "dimensions": "" - }, - "outputAnchors": [ - { - "id": "openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "name": "openAIEmbeddings", - "label": "OpenAIEmbeddings", - "description": "OpenAI API to generate embeddings for a given text", - "type": "OpenAIEmbeddings | Embeddings" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1154.293946350955, - "y": -589.6072684085893 - }, - "dragging": false - }, - { - "id": "stickyNote_0", - "position": { - "x": 753.8985547694751, - "y": -597.2403700691232 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_0", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_0-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "First, we rephrase the question using context from previous conversation.\n\nThis is to ensure that a follow-up question can be asked. For example:\n\n- What is the address of the Bakery shop?\n- What about the opening time?\n\nA rephrased question will be:\n- What is the opening time of the Bakery shop?\n\nThis ensure a better search to vector store, hence better results" - }, - "outputAnchors": [ - { - "id": "stickyNote_0-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 324, - "selected": false, - "positionAbsolute": { - "x": 753.8985547694751, - "y": -597.2403700691232 - }, - "dragging": false - }, - { - "id": "stickyNote_1", - "position": { - "x": 1904.305205441637, - "y": -241.45986503369568 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_1", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_1-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Second, rephrased question is used to do a similarity search to find relevant context" - }, - "outputAnchors": [ - { - "id": "stickyNote_1-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 62, - "selected": false, - "positionAbsolute": { - "x": 1904.305205441637, - "y": -241.45986503369568 - }, - "dragging": false - }, - { - "id": "stickyNote_2", - "position": { - "x": 2717.983596010546, - "y": -369.73223420234956 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_2", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_2-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Last, using the context from vector store, we instruct LLM to give a final response" - }, - "outputAnchors": [ - { - "id": "stickyNote_2-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 62, - "selected": false, - "positionAbsolute": { - "x": 2717.983596010546, - "y": -369.73223420234956 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "vectorStoreToDocument_0", - "sourceHandle": "vectorStoreToDocument_0-output-text-string|json", - "target": "chatPromptTemplate_0", - "targetHandle": "chatPromptTemplate_0-input-promptValues-json", - "type": "buttonedge", - "id": "vectorStoreToDocument_0-vectorStoreToDocument_0-output-text-string|json-chatPromptTemplate_0-chatPromptTemplate_0-input-promptValues-json", - "data": { - "label": "" - } - }, - { - "source": "promptTemplate_0", - "sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable", - "target": "llmChain_2", - "targetHandle": "llmChain_2-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable-llmChain_2-llmChain_2-input-prompt-BasePromptTemplate", - "data": { - "label": "" - } - }, - { - "source": "llmChain_2", - "sourceHandle": "llmChain_2-output-outputPrediction-string|json", - "target": "vectorStoreToDocument_0", - "targetHandle": "vectorStoreToDocument_0-input-query-string", - "type": "buttonedge", - "id": "llmChain_2-llmChain_2-output-outputPrediction-string|json-vectorStoreToDocument_0-vectorStoreToDocument_0-input-query-string", - "data": { - "label": "" - } - }, - { - "source": "chatPromptTemplate_0", - "sourceHandle": "chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate|Runnable", - "target": "llmChain_1", - "targetHandle": "llmChain_1-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "chatPromptTemplate_0-chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate|Runnable-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_0", - "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "llmChain_2", - "targetHandle": "llmChain_2-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-llmChain_2-llmChain_2-input-model-BaseLanguageModel", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_1", - "sourceHandle": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "llmChain_1", - "targetHandle": "llmChain_1-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_1-chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-llmChain_1-llmChain_1-input-model-BaseLanguageModel", - "data": { - "label": "" - } - }, - { - "source": "singlestore_0", - "sourceHandle": "singlestore_0-output-vectorStore-SingleStore|VectorStore", - "target": "vectorStoreToDocument_0", - "targetHandle": "vectorStoreToDocument_0-input-vectorStore-VectorStore", - "type": "buttonedge", - "id": "singlestore_0-singlestore_0-output-vectorStore-SingleStore|VectorStore-vectorStoreToDocument_0-vectorStoreToDocument_0-input-vectorStore-VectorStore", - "data": { - "label": "" - } - }, - { - "source": "openAIEmbeddings_0", - "sourceHandle": "openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "target": "singlestore_0", - "targetHandle": "singlestore_0-input-embeddings-Embeddings", - "type": "buttonedge", - "id": "openAIEmbeddings_0-openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings-singlestore_0-singlestore_0-input-embeddings-Embeddings", - "data": { - "label": "" - } - } - ] -} diff --git a/packages/server/marketplaces/chatflows/SQL Prompt.json b/packages/server/marketplaces/chatflows/SQL Prompt.json deleted file mode 100644 index 4e2524b4..00000000 --- a/packages/server/marketplaces/chatflows/SQL Prompt.json +++ /dev/null @@ -1,1983 +0,0 @@ -{ - "description": "Manually construct prompts to query a SQL database", - "usecases": ["SQL"], - "framework": ["Langchain"], - "nodes": [ - { - "width": 300, - "height": 511, - "id": "promptTemplate_0", - "position": { - "x": 384.4880563109088, - "y": 253.48974179902635 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_0", - "label": "Prompt Template", - "version": 1, - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate", "Runnable"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_0-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_0-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "template": "You are a MySQL expert. Given an input question, create a syntactically correct MySQL query to run.\nUnless otherwise specified, do not return more than {topK} rows.\n\nHere is the relevant table info:\n{schema}\n\nBelow are a number of examples of questions and their corresponding SQL queries.\n\nUser input: List all artists.\nSQL Query: SELECT * FROM Artist;\n\nUser input: Find all albums for the artist 'AC/DC'.\nSQL Query: SELECT * FROM Album WHERE ArtistId = (SELECT ArtistId FROM Artist WHERE Name = 'AC/DC');\n\nUser input: List all tracks in the 'Rock' genre.\nSQL Query: SELECT * FROM Track WHERE GenreId = (SELECT GenreId FROM Genre WHERE Name = 'Rock');\n\nUser input: Find the total duration of all tracks.\nSQL Query: SELECT SUM(Milliseconds) FROM Track;\n\nUser input: List all customers from Canada.\nSQL Query: SELECT * FROM Customer WHERE Country = 'Canada';\n\nUser input: {question}\nSQL query:", - "promptValues": "{\"schema\":\"{{customFunction_2.data.instance}}\",\"question\":\"{{question}}\",\"topK\":3}" - }, - "outputAnchors": [ - { - "id": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 384.4880563109088, - "y": 253.48974179902635 - }, - "dragging": false - }, - { - "width": 300, - "height": 507, - "id": "llmChain_0", - "position": { - "x": 770.4559230968546, - "y": -127.11351409346554 - }, - "type": "customNode", - "data": { - "id": "llmChain_0", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_0-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_0-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_0-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_0-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatOpenAI_0.data.instance}}", - "prompt": "{{promptTemplate_0.data.instance}}", - "outputParser": "", - "inputModeration": "", - "chainName": "SQL Query Chain" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_0-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_0-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "outputPrediction" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 770.4559230968546, - "y": -127.11351409346554 - }, - "dragging": false - }, - { - "width": 300, - "height": 669, - "id": "chatOpenAI_0", - "position": { - "x": 376.92707114970364, - "y": -666.8088336865496 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_0", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_0-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_0-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_0-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_0-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo-16k", - "temperature": "0", - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 376.92707114970364, - "y": -666.8088336865496 - }, - "dragging": false - }, - { - "width": 300, - "height": 669, - "id": "chatOpenAI_1", - "position": { - "x": 2653.726672579251, - "y": -665.8849139437705 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_1", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_1-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_1-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_1-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_1-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_1-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_1-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_1-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo-16k", - "temperature": "0", - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 2653.726672579251, - "y": -665.8849139437705 - }, - "dragging": false - }, - { - "width": 300, - "height": 507, - "id": "llmChain_1", - "position": { - "x": 3089.9937691022837, - "y": -109.24001734925716 - }, - "type": "customNode", - "data": { - "id": "llmChain_1", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_1-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_1-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_1-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_1-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_1-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatOpenAI_1.data.instance}}", - "prompt": "{{promptTemplate_1.data.instance}}", - "outputParser": "", - "inputModeration": "", - "chainName": "Final Chain" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_1-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_1-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "llmChain" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 3089.9937691022837, - "y": -109.24001734925716 - }, - "dragging": false - }, - { - "width": 300, - "height": 674, - "id": "customFunction_2", - "position": { - "x": -19.95227863012829, - "y": -125.50600296188355 - }, - "type": "customNode", - "data": { - "id": "customFunction_2", - "label": "Custom JS Function", - "version": 2, - "name": "customFunction", - "type": "CustomFunction", - "baseClasses": ["CustomFunction", "Utilities"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Execute custom javascript function", - "inputParams": [ - { - "label": "Input Variables", - "name": "functionInputVariables", - "description": "Input variables can be used in the function with prefix $. For example: $var", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "customFunction_2-input-functionInputVariables-json" - }, - { - "label": "Function Name", - "name": "functionName", - "type": "string", - "optional": true, - "placeholder": "My Function", - "id": "customFunction_2-input-functionName-string" - }, - { - "label": "Javascript Function", - "name": "javascriptFunction", - "type": "code", - "id": "customFunction_2-input-javascriptFunction-code" - } - ], - "inputAnchors": [], - "inputs": { - "functionInputVariables": "", - "functionName": "Get SQL Schema Prompt", - "javascriptFunction": "const HOST = 'singlestore-host.com';\nconst USER = 'admin';\nconst PASSWORD = 'mypassword';\nconst DATABASE = 'mydb';\nconst TABLE = 'samples';\nconst mysql = require('mysql2/promise');\n\nlet sqlSchemaPrompt;\n\n/**\n * Ideal prompt contains schema info and examples\n * Follows best practices as specified form https://arxiv.org/abs/2204.00498\n * =========================================\n * CREATE TABLE samples (firstName varchar NOT NULL, lastName varchar)\n * SELECT * FROM samples LIMIT 3\n * firstName lastName\n * Stephen Tyler\n * Jack McGinnis\n * Steven Repici\n * =========================================\n*/\nfunction getSQLPrompt() {\n return new Promise(async (resolve, reject) => {\n try {\n const singleStoreConnection = mysql.createPool({\n host: HOST,\n user: USER,\n password: PASSWORD,\n database: DATABASE,\n });\n \n // Get schema info\n const [schemaInfo] = await singleStoreConnection.execute(\n `SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = \"${TABLE}\"`\n );\n \n const createColumns = [];\n const columnNames = [];\n \n for (const schemaData of schemaInfo) {\n columnNames.push(`${schemaData['COLUMN_NAME']}`);\n createColumns.push(`${schemaData['COLUMN_NAME']} ${schemaData['COLUMN_TYPE']} ${schemaData['IS_NULLABLE'] === 'NO' ? 'NOT NULL' : ''}`);\n }\n \n const sqlCreateTableQuery = `CREATE TABLE samples (${createColumns.join(', ')})`;\n const sqlSelectTableQuery = `SELECT * FROM samples LIMIT 3`;\n \n // Get first 3 rows\n const [rows] = await singleStoreConnection.execute(\n sqlSelectTableQuery,\n );\n \n const allValues = [];\n for (const row of rows) {\n const rowValues = [];\n for (const colName in row) {\n rowValues.push(row[colName]);\n }\n allValues.push(rowValues.join(' '));\n }\n \n sqlSchemaPrompt = sqlCreateTableQuery + '\\n' + sqlSelectTableQuery + '\\n' + columnNames.join(' ') + '\\n' + allValues.join('\\n');\n \n resolve();\n } catch (e) {\n console.error(e);\n return reject(e);\n }\n });\n}\n\nasync function main() {\n await getSQLPrompt();\n}\n\nawait main();\n\nreturn sqlSchemaPrompt;" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "description": "", - "options": [ - { - "id": "customFunction_2-output-output-string|number|boolean|json|array", - "name": "output", - "label": "Output", - "description": "", - "type": "string | number | boolean | json | array" - }, - { - "id": "customFunction_2-output-EndingNode-CustomFunction", - "name": "EndingNode", - "label": "Ending Node", - "description": "", - "type": "CustomFunction" - } - ], - "default": "output" - } - ], - "outputs": { - "output": "output" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": -19.95227863012829, - "y": -125.50600296188355 - }, - "dragging": false - }, - { - "width": 300, - "height": 674, - "id": "customFunction_1", - "position": { - "x": 1887.4670208331604, - "y": -275.95340782935716 - }, - "type": "customNode", - "data": { - "id": "customFunction_1", - "label": "Custom JS Function", - "version": 2, - "name": "customFunction", - "type": "CustomFunction", - "baseClasses": ["CustomFunction", "Utilities"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Execute custom javascript function", - "inputParams": [ - { - "label": "Input Variables", - "name": "functionInputVariables", - "description": "Input variables can be used in the function with prefix $. For example: $var", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "customFunction_1-input-functionInputVariables-json" - }, - { - "label": "Function Name", - "name": "functionName", - "type": "string", - "optional": true, - "placeholder": "My Function", - "id": "customFunction_1-input-functionName-string" - }, - { - "label": "Javascript Function", - "name": "javascriptFunction", - "type": "code", - "id": "customFunction_1-input-javascriptFunction-code" - } - ], - "inputAnchors": [], - "inputs": { - "functionInputVariables": "{\"sqlQuery\":\"{{setVariable_1.data.instance}}\"}", - "functionName": "Run SQL Query", - "javascriptFunction": "const HOST = 'singlestore-host.com';\nconst USER = 'admin';\nconst PASSWORD = 'mypassword';\nconst DATABASE = 'mydb';\nconst TABLE = 'samples';\nconst mysql = require('mysql2/promise');\n\nlet result;\n\nfunction getSQLResult() {\n return new Promise(async (resolve, reject) => {\n try {\n const singleStoreConnection = mysql.createPool({\n host: HOST,\n user: USER,\n password: PASSWORD,\n database: DATABASE,\n });\n \n const [rows] = await singleStoreConnection.execute(\n $sqlQuery\n );\n \n result = JSON.stringify(rows)\n \n resolve();\n } catch (e) {\n console.error(e);\n return reject(e);\n }\n });\n}\n\nasync function main() {\n await getSQLResult();\n}\n\nawait main();\n\nreturn result;" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "description": "", - "options": [ - { - "id": "customFunction_1-output-output-string|number|boolean|json|array", - "name": "output", - "label": "Output", - "description": "", - "type": "string | number | boolean | json | array" - }, - { - "id": "customFunction_1-output-EndingNode-CustomFunction", - "name": "EndingNode", - "label": "Ending Node", - "description": "", - "type": "CustomFunction" - } - ], - "default": "output" - } - ], - "outputs": { - "output": "output" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1887.4670208331604, - "y": -275.95340782935716 - }, - "dragging": false - }, - { - "width": 300, - "height": 511, - "id": "promptTemplate_1", - "position": { - "x": 2655.2632506040304, - "y": 218.145615216618 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_1", - "label": "Prompt Template", - "version": 1, - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate", "Runnable"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_1-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_1-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "template": "Given the following user question, corresponding SQL query, and SQL result, answer the user question as details as possible.\n\nQuestion: {question}\n\nSQL Query: {sqlQuery}\n\nSQL Result: {sqlResponse}\n\nAnswer:\n", - "promptValues": "{\"question\":\"{{question}}\",\"sqlResponse\":\"{{customFunction_1.data.instance}}\",\"sqlQuery\":\"{{getVariable_1.data.instance}}\"}" - }, - "outputAnchors": [ - { - "id": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "dragging": false, - "positionAbsolute": { - "x": 2655.2632506040304, - "y": 218.145615216618 - } - }, - { - "width": 300, - "height": 304, - "id": "getVariable_1", - "position": { - "x": 2272.8555266616872, - "y": 24.11364076336241 - }, - "type": "customNode", - "data": { - "id": "getVariable_1", - "label": "Get Variable", - "version": 2, - "name": "getVariable", - "type": "GetVariable", - "baseClasses": ["GetVariable", "Utilities"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Get variable that was saved using Set Variable node", - "inputParams": [ - { - "label": "Variable Name", - "name": "variableName", - "type": "string", - "placeholder": "var1", - "id": "getVariable_1-input-variableName-string" - } - ], - "inputAnchors": [], - "inputs": { - "variableName": "sqlQuery" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "description": "", - "options": [ - { - "id": "getVariable_1-output-output-string|number|boolean|json|array", - "name": "output", - "label": "Output", - "description": "", - "type": "string | number | boolean | json | array" - } - ], - "default": "output" - } - ], - "outputs": { - "output": "output" - }, - "selected": false - }, - "positionAbsolute": { - "x": 2272.8555266616872, - "y": 24.11364076336241 - }, - "selected": false, - "dragging": false - }, - { - "width": 300, - "height": 355, - "id": "setVariable_1", - "position": { - "x": 1516.338224315744, - "y": -133.6986023683283 - }, - "type": "customNode", - "data": { - "id": "setVariable_1", - "label": "Set Variable", - "version": 2, - "name": "setVariable", - "type": "SetVariable", - "baseClasses": ["SetVariable", "Utilities"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Set variable which can be retrieved at a later stage. Variable is only available during runtime.", - "inputParams": [ - { - "label": "Variable Name", - "name": "variableName", - "type": "string", - "placeholder": "var1", - "id": "setVariable_1-input-variableName-string" - } - ], - "inputAnchors": [ - { - "label": "Input", - "name": "input", - "type": "string | number | boolean | json | array", - "optional": true, - "list": true, - "id": "setVariable_1-input-input-string | number | boolean | json | array" - } - ], - "inputs": { - "input": ["{{ifElseFunction_0.data.instance}}"], - "variableName": "sqlQuery" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "description": "", - "options": [ - { - "id": "setVariable_1-output-output-string|number|boolean|json|array", - "name": "output", - "label": "Output", - "description": "", - "type": "string | number | boolean | json | array" - } - ], - "default": "output" - } - ], - "outputs": { - "output": "output" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1516.338224315744, - "y": -133.6986023683283 - }, - "dragging": false - }, - { - "width": 300, - "height": 765, - "id": "ifElseFunction_0", - "position": { - "x": 1147.8020838770517, - "y": -237.39478763322148 - }, - "type": "customNode", - "data": { - "id": "ifElseFunction_0", - "label": "IfElse Function", - "version": 2, - "name": "ifElseFunction", - "type": "IfElseFunction", - "baseClasses": ["IfElseFunction", "Utilities"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Split flows based on If Else javascript functions", - "inputParams": [ - { - "label": "Input Variables", - "name": "functionInputVariables", - "description": "Input variables can be used in the function with prefix $. For example: $var", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "ifElseFunction_0-input-functionInputVariables-json" - }, - { - "label": "IfElse Name", - "name": "functionName", - "type": "string", - "optional": true, - "placeholder": "If Condition Match", - "id": "ifElseFunction_0-input-functionName-string" - }, - { - "label": "If Function", - "name": "ifFunction", - "description": "Function must return a value", - "type": "code", - "rows": 2, - "default": "if (\"hello\" == \"hello\") {\n return true;\n}", - "id": "ifElseFunction_0-input-ifFunction-code" - }, - { - "label": "Else Function", - "name": "elseFunction", - "description": "Function must return a value", - "type": "code", - "rows": 2, - "default": "return false;", - "id": "ifElseFunction_0-input-elseFunction-code" - } - ], - "inputAnchors": [], - "inputs": { - "functionInputVariables": "{\"sqlQuery\":\"{{llmChain_0.data.instance}}\"}", - "functionName": "IF SQL Query contains SELECT and WHERE", - "ifFunction": "const sqlQuery = $sqlQuery.trim();\n\nconst regex = /SELECT\\s.*?(?:\\n|$)/gi;\n\n// Extracting the SQL part\nconst matches = sqlQuery.match(regex);\nconst cleanSql = matches ? matches[0].trim() : \"\";\n\nif (cleanSql.includes(\"SELECT\") && cleanSql.includes(\"WHERE\")) {\n return cleanSql;\n}", - "elseFunction": "return $sqlQuery;" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "description": "", - "options": [ - { - "id": "ifElseFunction_0-output-returnTrue-string|number|boolean|json|array", - "name": "returnTrue", - "label": "True", - "description": "", - "type": "string | number | boolean | json | array" - }, - { - "id": "ifElseFunction_0-output-returnFalse-string|number|boolean|json|array", - "name": "returnFalse", - "label": "False", - "description": "", - "type": "string | number | boolean | json | array" - } - ], - "default": "returnTrue" - } - ], - "outputs": { - "output": "returnTrue" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1147.8020838770517, - "y": -237.39478763322148 - }, - "dragging": false - }, - { - "width": 300, - "height": 511, - "id": "promptTemplate_2", - "position": { - "x": 1193.7489579044463, - "y": 615.4009446588724 - }, - "type": "customNode", - "data": { - "id": "promptTemplate_2", - "label": "Prompt Template", - "version": 1, - "name": "promptTemplate", - "type": "PromptTemplate", - "baseClasses": ["PromptTemplate", "BaseStringPromptTemplate", "BasePromptTemplate", "Runnable"], - "category": "Prompts", - "description": "Schema to represent a basic prompt for an LLM", - "inputParams": [ - { - "label": "Template", - "name": "template", - "type": "string", - "rows": 4, - "placeholder": "What is a good name for a company that makes {product}?", - "id": "promptTemplate_2-input-template-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "promptTemplate_2-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "template": "Politely say \"I'm not able to answer query\"", - "promptValues": "{\"schema\":\"{{setVariable_0.data.instance}}\",\"question\":\"{{question}}\"}" - }, - "outputAnchors": [ - { - "id": "promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable", - "name": "promptTemplate", - "label": "PromptTemplate", - "type": "PromptTemplate | BaseStringPromptTemplate | BasePromptTemplate | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1193.7489579044463, - "y": 615.4009446588724 - }, - "dragging": false - }, - { - "width": 300, - "height": 669, - "id": "chatOpenAI_2", - "position": { - "x": 1545.1023725538003, - "y": 493.5495798408175 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_2", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_2-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_2-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_2-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_2-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_2-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_2-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_2-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo-16k", - "temperature": "0.7", - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1545.1023725538003, - "y": 493.5495798408175 - }, - "dragging": false - }, - { - "width": 300, - "height": 507, - "id": "llmChain_2", - "position": { - "x": 1914.509823868027, - "y": 622.3435967391327 - }, - "type": "customNode", - "data": { - "id": "llmChain_2", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_2-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_2-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_2-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_2-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_2-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatOpenAI_2.data.instance}}", - "prompt": "{{promptTemplate_2.data.instance}}", - "outputParser": "", - "inputModeration": "", - "chainName": "Fallback Chain" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_2-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_2-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "llmChain" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1914.509823868027, - "y": 622.3435967391327 - }, - "dragging": false - }, - { - "id": "stickyNote_0", - "position": { - "x": -18.950231412347364, - "y": -192.2980180516393 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_0", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_0-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "First, get SQL database schema" - }, - "outputAnchors": [ - { - "id": "stickyNote_0-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 42, - "selected": false, - "positionAbsolute": { - "x": -18.950231412347364, - "y": -192.2980180516393 - }, - "dragging": false - }, - { - "id": "stickyNote_1", - "position": { - "x": 1510.6324834799852, - "y": -221.78240261184442 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_1", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_1-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Save as variable to be used at the last Prompt Template" - }, - "outputAnchors": [ - { - "id": "stickyNote_1-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 62, - "selected": false, - "positionAbsolute": { - "x": 1510.6324834799852, - "y": -221.78240261184442 - }, - "dragging": false - }, - { - "id": "stickyNote_2", - "position": { - "x": 386.88037412001086, - "y": 47.66735767574478 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_2", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_2-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Instruct LLM to return a SQL query using the schema.\n\nRecommend to give few examples for higher accuracy. \n\nChange the prompt accordingly to suit the type of database you are using" - }, - "outputAnchors": [ - { - "id": "stickyNote_2-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 183, - "selected": false, - "positionAbsolute": { - "x": 386.88037412001086, - "y": 47.66735767574478 - }, - "dragging": false - }, - { - "id": "stickyNote_3", - "position": { - "x": 1148.366177280569, - "y": -330.2148999791981 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_3", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_3-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Check if SQL Query is valid\n\nIf not, avoid executing it and return to user " - }, - "outputAnchors": [ - { - "id": "stickyNote_3-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 82, - "selected": false, - "positionAbsolute": { - "x": 1148.366177280569, - "y": -330.2148999791981 - }, - "dragging": false - }, - { - "id": "stickyNote_4", - "position": { - "x": 1881.2554569013519, - "y": -435.79147130381756 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_4", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_4-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Execute the SQL query after validated, and get the list of results back.\n\nTo avoid long list of results overflowing token limit, try capping the length of result here" - }, - "outputAnchors": [ - { - "id": "stickyNote_4-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 143, - "selected": false, - "positionAbsolute": { - "x": 1881.2554569013519, - "y": -435.79147130381756 - }, - "dragging": false - }, - { - "id": "stickyNote_5", - "position": { - "x": 1545.0242031958799, - "y": 428.37859733277077 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_5", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_5-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Fallback answer if SQL query is not valid" - }, - "outputAnchors": [ - { - "id": "stickyNote_5-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 42, - "selected": false, - "positionAbsolute": { - "x": 1545.0242031958799, - "y": 428.37859733277077 - }, - "dragging": false - }, - { - "id": "stickyNote_6", - "position": { - "x": 2653.037036258241, - "y": 53.55638699917168 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_6", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_6-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "This is the final prompt.\n\nCombine the following:\nQuestion + SQL query + SQL result\n\nto generate a final answer" - }, - "outputAnchors": [ - { - "id": "stickyNote_6-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 143, - "selected": false, - "positionAbsolute": { - "x": 2653.037036258241, - "y": 53.55638699917168 - }, - "dragging": false - }, - { - "id": "stickyNote_7", - "position": { - "x": 2267.355938520518, - "y": -56.64296923028309 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_7", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_7-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "Get the saved variable value to be used in prompt" - }, - "outputAnchors": [ - { - "id": "stickyNote_7-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 62, - "selected": false, - "positionAbsolute": { - "x": 2267.355938520518, - "y": -56.64296923028309 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "promptTemplate_0", - "sourceHandle": "promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "promptTemplate_0-promptTemplate_0-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable-llmChain_0-llmChain_0-input-prompt-BasePromptTemplate", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_0", - "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-llmChain_0-llmChain_0-input-model-BaseLanguageModel", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_1", - "sourceHandle": "chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "llmChain_1", - "targetHandle": "llmChain_1-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_1-chatOpenAI_1-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-llmChain_1-llmChain_1-input-model-BaseLanguageModel", - "data": { - "label": "" - } - }, - { - "source": "customFunction_1", - "sourceHandle": "customFunction_1-output-output-string|number|boolean|json|array", - "target": "promptTemplate_1", - "targetHandle": "promptTemplate_1-input-promptValues-json", - "type": "buttonedge", - "id": "customFunction_1-customFunction_1-output-output-string|number|boolean|json|array-promptTemplate_1-promptTemplate_1-input-promptValues-json", - "data": { - "label": "" - } - }, - { - "source": "promptTemplate_1", - "sourceHandle": "promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable", - "target": "llmChain_1", - "targetHandle": "llmChain_1-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "promptTemplate_1-promptTemplate_1-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable-llmChain_1-llmChain_1-input-prompt-BasePromptTemplate", - "data": { - "label": "" - } - }, - { - "source": "getVariable_1", - "sourceHandle": "getVariable_1-output-output-string|number|boolean|json|array", - "target": "promptTemplate_1", - "targetHandle": "promptTemplate_1-input-promptValues-json", - "type": "buttonedge", - "id": "getVariable_1-getVariable_1-output-output-string|number|boolean|json|array-promptTemplate_1-promptTemplate_1-input-promptValues-json", - "data": { - "label": "" - } - }, - { - "source": "setVariable_1", - "sourceHandle": "setVariable_1-output-output-string|number|boolean|json|array", - "target": "customFunction_1", - "targetHandle": "customFunction_1-input-functionInputVariables-json", - "type": "buttonedge", - "id": "setVariable_1-setVariable_1-output-output-string|number|boolean|json|array-customFunction_1-customFunction_1-input-functionInputVariables-json", - "data": { - "label": "" - } - }, - { - "source": "llmChain_0", - "sourceHandle": "llmChain_0-output-outputPrediction-string|json", - "target": "ifElseFunction_0", - "targetHandle": "ifElseFunction_0-input-functionInputVariables-json", - "type": "buttonedge", - "id": "llmChain_0-llmChain_0-output-outputPrediction-string|json-ifElseFunction_0-ifElseFunction_0-input-functionInputVariables-json" - }, - { - "source": "ifElseFunction_0", - "sourceHandle": "ifElseFunction_0-output-returnTrue-string|number|boolean|json|array", - "target": "setVariable_1", - "targetHandle": "setVariable_1-input-input-string | number | boolean | json | array", - "type": "buttonedge", - "id": "ifElseFunction_0-ifElseFunction_0-output-returnTrue-string|number|boolean|json|array-setVariable_1-setVariable_1-input-input-string | number | boolean | json | array" - }, - { - "source": "ifElseFunction_0", - "sourceHandle": "ifElseFunction_0-output-returnFalse-string|number|boolean|json|array", - "target": "promptTemplate_2", - "targetHandle": "promptTemplate_2-input-promptValues-json", - "type": "buttonedge", - "id": "ifElseFunction_0-ifElseFunction_0-output-returnFalse-string|number|boolean|json|array-promptTemplate_2-promptTemplate_2-input-promptValues-json" - }, - { - "source": "chatOpenAI_2", - "sourceHandle": "chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "llmChain_2", - "targetHandle": "llmChain_2-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_2-chatOpenAI_2-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-llmChain_2-llmChain_2-input-model-BaseLanguageModel" - }, - { - "source": "promptTemplate_2", - "sourceHandle": "promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable", - "target": "llmChain_2", - "targetHandle": "llmChain_2-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "promptTemplate_2-promptTemplate_2-output-promptTemplate-PromptTemplate|BaseStringPromptTemplate|BasePromptTemplate|Runnable-llmChain_2-llmChain_2-input-prompt-BasePromptTemplate" - }, - { - "source": "customFunction_2", - "sourceHandle": "customFunction_2-output-output-string|number|boolean|json|array", - "target": "promptTemplate_0", - "targetHandle": "promptTemplate_0-input-promptValues-json", - "type": "buttonedge", - "id": "customFunction_2-customFunction_2-output-output-string|number|boolean|json|array-promptTemplate_0-promptTemplate_0-input-promptValues-json" - } - ] -} diff --git a/packages/server/marketplaces/chatflows/Simple Chat Engine.json b/packages/server/marketplaces/chatflows/Simple Chat Engine.json index 5b9429cc..5aa600cb 100644 --- a/packages/server/marketplaces/chatflows/Simple Chat Engine.json +++ b/packages/server/marketplaces/chatflows/Simple Chat Engine.json @@ -1,6 +1,6 @@ { "description": "Simple chat engine to handle back and forth conversations using LlamaIndex", - "usecases": ["Chatbot"], + "usecases": ["Basic"], "framework": ["LlamaIndex"], "nodes": [ { diff --git a/packages/server/marketplaces/chatflows/Structured Output Parser.json b/packages/server/marketplaces/chatflows/Structured Output Parser.json deleted file mode 100644 index e8067632..00000000 --- a/packages/server/marketplaces/chatflows/Structured Output Parser.json +++ /dev/null @@ -1,490 +0,0 @@ -{ - "description": "Return response as a specified JSON structure instead of a string/text", - "framework": ["Langchain"], - "usecases": ["Extraction"], - "nodes": [ - { - "width": 300, - "height": 574, - "id": "chatOpenAI_0", - "position": { - "x": 845.3961479115309, - "y": -205.74401580699953 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_0", - "label": "ChatOpenAI", - "version": 6.0, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_0-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_0-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_0-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_0-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo", - "temperature": "0", - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 845.3961479115309, - "y": -205.74401580699953 - }, - "dragging": false - }, - { - "width": 300, - "height": 456, - "id": "llmChain_0", - "position": { - "x": 1229.1699649849293, - "y": 245.55173505632646 - }, - "type": "customNode", - "data": { - "id": "llmChain_0", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_0-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_0-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_0-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_0-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatOpenAI_0.data.instance}}", - "prompt": "{{chatPromptTemplate_0.data.instance}}", - "outputParser": "{{structuredOutputParser_0.data.instance}}", - "chainName": "", - "inputModeration": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_0-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_0-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "llmChain" - }, - "selected": false - }, - "positionAbsolute": { - "x": 1229.1699649849293, - "y": 245.55173505632646 - }, - "selected": false - }, - { - "width": 300, - "height": 652, - "id": "chatPromptTemplate_0", - "position": { - "x": 501.1597501123828, - "y": -154.43917602832562 - }, - "type": "customNode", - "data": { - "id": "chatPromptTemplate_0", - "label": "Chat Prompt Template", - "version": 1, - "name": "chatPromptTemplate", - "type": "ChatPromptTemplate", - "baseClasses": ["ChatPromptTemplate", "BaseChatPromptTemplate", "BasePromptTemplate", "Runnable"], - "category": "Prompts", - "description": "Schema to represent a chat prompt", - "inputParams": [ - { - "label": "System Message", - "name": "systemMessagePrompt", - "type": "string", - "rows": 4, - "placeholder": "You are a helpful assistant that translates {input_language} to {output_language}.", - "id": "chatPromptTemplate_0-input-systemMessagePrompt-string" - }, - { - "label": "Human Message", - "name": "humanMessagePrompt", - "type": "string", - "rows": 4, - "placeholder": "{text}", - "id": "chatPromptTemplate_0-input-humanMessagePrompt-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "chatPromptTemplate_0-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "systemMessagePrompt": "Answer user's question as best you can", - "humanMessagePrompt": "{text}", - "promptValues": "" - }, - "outputAnchors": [ - { - "id": "chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate|Runnable", - "name": "chatPromptTemplate", - "label": "ChatPromptTemplate", - "type": "ChatPromptTemplate | BaseChatPromptTemplate | BasePromptTemplate | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 501.1597501123828, - "y": -154.43917602832562 - }, - "dragging": false - }, - { - "width": 300, - "height": 328, - "id": "structuredOutputParser_0", - "position": { - "x": 170.3869571939727, - "y": 343.9298288967859 - }, - "type": "customNode", - "data": { - "id": "structuredOutputParser_0", - "label": "Structured Output Parser", - "version": 1, - "name": "structuredOutputParser", - "type": "StructuredOutputParser", - "baseClasses": ["StructuredOutputParser", "BaseLLMOutputParser", "Runnable"], - "category": "Output Parsers", - "description": "Parse the output of an LLM call into a given (JSON) structure.", - "inputParams": [ - { - "label": "Autofix", - "name": "autofixParser", - "type": "boolean", - "optional": true, - "description": "In the event that the first call fails, will make another call to the model to fix any errors.", - "id": "structuredOutputParser_0-input-autofixParser-boolean" - }, - { - "label": "JSON Structure", - "name": "jsonStructure", - "type": "datagrid", - "description": "JSON structure for LLM to return", - "datagrid": [ - { - "field": "property", - "headerName": "Property", - "editable": true - }, - { - "field": "type", - "headerName": "Type", - "type": "singleSelect", - "valueOptions": ["string", "number", "boolean"], - "editable": true - }, - { - "field": "description", - "headerName": "Description", - "editable": true, - "flex": 1 - } - ], - "default": [ - { - "property": "answer", - "type": "string", - "description": "answer to the user's question" - }, - { - "property": "source", - "type": "string", - "description": "sources used to answer the question, should be websites" - } - ], - "additionalParams": true, - "id": "structuredOutputParser_0-input-jsonStructure-datagrid" - } - ], - "inputAnchors": [], - "inputs": { - "autofixParser": true, - "jsonStructure": [ - { - "property": "answer", - "type": "string", - "description": "answer to the user's question" - }, - { - "property": "source", - "type": "string", - "description": "sources used to answer the question, should be websites" - } - ] - }, - "outputAnchors": [ - { - "id": "structuredOutputParser_0-output-structuredOutputParser-StructuredOutputParser|BaseLLMOutputParser|Runnable", - "name": "structuredOutputParser", - "label": "StructuredOutputParser", - "type": "StructuredOutputParser | BaseLLMOutputParser | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 170.3869571939727, - "y": 343.9298288967859 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "chatOpenAI_0", - "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-llmChain_0-llmChain_0-input-model-BaseLanguageModel", - "data": { - "label": "" - } - }, - { - "source": "chatPromptTemplate_0", - "sourceHandle": "chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate|Runnable", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "chatPromptTemplate_0-chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate|Runnable-llmChain_0-llmChain_0-input-prompt-BasePromptTemplate", - "data": { - "label": "" - } - }, - { - "source": "structuredOutputParser_0", - "sourceHandle": "structuredOutputParser_0-output-structuredOutputParser-StructuredOutputParser|BaseLLMOutputParser|Runnable", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-outputParser-BaseLLMOutputParser", - "type": "buttonedge", - "id": "structuredOutputParser_0-structuredOutputParser_0-output-structuredOutputParser-StructuredOutputParser|BaseLLMOutputParser|Runnable-llmChain_0-llmChain_0-input-outputParser-BaseLLMOutputParser", - "data": { - "label": "" - } - } - ] -} diff --git a/packages/server/marketplaces/chatflows/Tool Agent.json b/packages/server/marketplaces/chatflows/Tool Agent.json new file mode 100644 index 00000000..057b2b6e --- /dev/null +++ b/packages/server/marketplaces/chatflows/Tool Agent.json @@ -0,0 +1,631 @@ +{ + "description": "An agent designed to use tools and LLM with function calling capability to provide responses", + "usecases": ["Agent"], + "framework": ["Langchain"], + "nodes": [ + { + "width": 300, + "height": 149, + "id": "calculator_1", + "position": { + "x": 800.5125025564965, + "y": 72.40592063242738 + }, + "type": "customNode", + "data": { + "id": "calculator_1", + "label": "Calculator", + "version": 1, + "name": "calculator", + "type": "Calculator", + "baseClasses": ["Calculator", "Tool", "StructuredTool", "BaseLangChain"], + "category": "Tools", + "description": "Perform calculations on response", + "inputParams": [], + "inputAnchors": [], + "inputs": {}, + "outputAnchors": [ + { + "id": "calculator_1-output-calculator-Calculator|Tool|StructuredTool|BaseLangChain", + "name": "calculator", + "label": "Calculator", + "type": "Calculator | Tool | StructuredTool | BaseLangChain" + } + ], + "outputs": {}, + "selected": false + }, + "positionAbsolute": { + "x": 800.5125025564965, + "y": 72.40592063242738 + }, + "selected": false, + "dragging": false + }, + { + "width": 300, + "height": 259, + "id": "bufferMemory_1", + "position": { + "x": 607.6260576768354, + "y": 584.7920541862369 + }, + "type": "customNode", + "data": { + "id": "bufferMemory_1", + "label": "Buffer Memory", + "version": 2, + "name": "bufferMemory", + "type": "BufferMemory", + "baseClasses": ["BufferMemory", "BaseChatMemory", "BaseMemory"], + "category": "Memory", + "description": "Retrieve chat messages stored in database", + "inputParams": [ + { + "label": "Session Id", + "name": "sessionId", + "type": "string", + "description": "If not specified, a random id will be used. Learn more", + "default": "", + "additionalParams": true, + "optional": true, + "id": "bufferMemory_1-input-sessionId-string" + }, + { + "label": "Memory Key", + "name": "memoryKey", + "type": "string", + "default": "chat_history", + "additionalParams": true, + "id": "bufferMemory_1-input-memoryKey-string" + } + ], + "inputAnchors": [], + "inputs": { + "sessionId": "", + "memoryKey": "chat_history" + }, + "outputAnchors": [ + { + "id": "bufferMemory_1-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory", + "name": "bufferMemory", + "label": "BufferMemory", + "type": "BufferMemory | BaseChatMemory | BaseMemory" + } + ], + "outputs": {}, + "selected": false + }, + "positionAbsolute": { + "x": 607.6260576768354, + "y": 584.7920541862369 + }, + "selected": false, + "dragging": false + }, + { + "width": 300, + "height": 282, + "id": "serpAPI_0", + "position": { + "x": 439.29908455642476, + "y": 48.06000078669291 + }, + "type": "customNode", + "data": { + "id": "serpAPI_0", + "label": "Serp API", + "version": 1, + "name": "serpAPI", + "type": "SerpAPI", + "baseClasses": ["SerpAPI", "Tool", "StructuredTool"], + "category": "Tools", + "description": "Wrapper around SerpAPI - a real-time API to access Google search results", + "inputParams": [ + { + "label": "Connect Credential", + "name": "credential", + "type": "credential", + "credentialNames": ["serpApi"], + "id": "serpAPI_0-input-credential-credential" + } + ], + "inputAnchors": [], + "inputs": {}, + "outputAnchors": [ + { + "id": "serpAPI_0-output-serpAPI-SerpAPI|Tool|StructuredTool", + "name": "serpAPI", + "label": "SerpAPI", + "type": "SerpAPI | Tool | StructuredTool" + } + ], + "outputs": {}, + "selected": false + }, + "selected": false, + "positionAbsolute": { + "x": 439.29908455642476, + "y": 48.06000078669291 + }, + "dragging": false + }, + { + "width": 300, + "height": 772, + "id": "chatOpenAI_0", + "position": { + "x": 97.01321406237057, + "y": 63.67664262280914 + }, + "type": "customNode", + "data": { + "id": "chatOpenAI_0", + "label": "ChatOpenAI", + "version": 8.2, + "name": "chatOpenAI", + "type": "ChatOpenAI", + "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], + "category": "Chat Models", + "description": "Wrapper around OpenAI large language models that use the Chat endpoint", + "inputParams": [ + { + "label": "Connect Credential", + "name": "credential", + "type": "credential", + "credentialNames": ["openAIApi"], + "id": "chatOpenAI_0-input-credential-credential", + "display": true + }, + { + "label": "Model Name", + "name": "modelName", + "type": "asyncOptions", + "loadMethod": "listModels", + "default": "gpt-4o-mini", + "id": "chatOpenAI_0-input-modelName-asyncOptions", + "display": true + }, + { + "label": "Temperature", + "name": "temperature", + "type": "number", + "step": 0.1, + "default": 0.9, + "optional": true, + "id": "chatOpenAI_0-input-temperature-number", + "display": true + }, + { + "label": "Streaming", + "name": "streaming", + "type": "boolean", + "default": true, + "optional": true, + "additionalParams": true, + "id": "chatOpenAI_0-input-streaming-boolean", + "display": true + }, + { + "label": "Max Tokens", + "name": "maxTokens", + "type": "number", + "step": 1, + "optional": true, + "additionalParams": true, + "id": "chatOpenAI_0-input-maxTokens-number", + "display": true + }, + { + "label": "Top Probability", + "name": "topP", + "type": "number", + "step": 0.1, + "optional": true, + "additionalParams": true, + "id": "chatOpenAI_0-input-topP-number", + "display": true + }, + { + "label": "Frequency Penalty", + "name": "frequencyPenalty", + "type": "number", + "step": 0.1, + "optional": true, + "additionalParams": true, + "id": "chatOpenAI_0-input-frequencyPenalty-number", + "display": true + }, + { + "label": "Presence Penalty", + "name": "presencePenalty", + "type": "number", + "step": 0.1, + "optional": true, + "additionalParams": true, + "id": "chatOpenAI_0-input-presencePenalty-number", + "display": true + }, + { + "label": "Timeout", + "name": "timeout", + "type": "number", + "step": 1, + "optional": true, + "additionalParams": true, + "id": "chatOpenAI_0-input-timeout-number", + "display": true + }, + { + "label": "Strict Tool Calling", + "name": "strictToolCalling", + "type": "boolean", + "description": "Whether the model supports the `strict` argument when passing in tools. If not specified, the `strict` argument will not be passed to OpenAI.", + "optional": true, + "additionalParams": true, + "id": "chatOpenAI_0-input-strictToolCalling-boolean", + "display": true + }, + { + "label": "Stop Sequence", + "name": "stopSequence", + "type": "string", + "rows": 4, + "optional": true, + "description": "List of stop words to use when generating. Use comma to separate multiple stop words.", + "additionalParams": true, + "id": "chatOpenAI_0-input-stopSequence-string", + "display": true + }, + { + "label": "BasePath", + "name": "basepath", + "type": "string", + "optional": true, + "additionalParams": true, + "id": "chatOpenAI_0-input-basepath-string", + "display": true + }, + { + "label": "Proxy Url", + "name": "proxyUrl", + "type": "string", + "optional": true, + "additionalParams": true, + "id": "chatOpenAI_0-input-proxyUrl-string", + "display": true + }, + { + "label": "BaseOptions", + "name": "baseOptions", + "type": "json", + "optional": true, + "additionalParams": true, + "id": "chatOpenAI_0-input-baseOptions-json", + "display": true + }, + { + "label": "Allow Image Uploads", + "name": "allowImageUploads", + "type": "boolean", + "description": "Allow image input. Refer to the docs for more details.", + "default": false, + "optional": true, + "id": "chatOpenAI_0-input-allowImageUploads-boolean", + "display": true + }, + { + "label": "Image Resolution", + "description": "This parameter controls the resolution in which the model views the image.", + "name": "imageResolution", + "type": "options", + "options": [ + { + "label": "Low", + "name": "low" + }, + { + "label": "High", + "name": "high" + }, + { + "label": "Auto", + "name": "auto" + } + ], + "default": "low", + "optional": false, + "show": { + "allowImageUploads": true + }, + "id": "chatOpenAI_0-input-imageResolution-options", + "display": true + }, + { + "label": "Reasoning Effort", + "description": "Constrains effort on reasoning for reasoning models. Only applicable for o1 and o3 models.", + "name": "reasoningEffort", + "type": "options", + "options": [ + { + "label": "Low", + "name": "low" + }, + { + "label": "Medium", + "name": "medium" + }, + { + "label": "High", + "name": "high" + } + ], + "default": "medium", + "optional": false, + "additionalParams": true, + "id": "chatOpenAI_0-input-reasoningEffort-options", + "display": true + } + ], + "inputAnchors": [ + { + "label": "Cache", + "name": "cache", + "type": "BaseCache", + "optional": true, + "id": "chatOpenAI_0-input-cache-BaseCache", + "display": true + } + ], + "inputs": { + "cache": "", + "modelName": "gpt-4o-mini", + "temperature": 0.9, + "streaming": true, + "maxTokens": "", + "topP": "", + "frequencyPenalty": "", + "presencePenalty": "", + "timeout": "", + "strictToolCalling": "", + "stopSequence": "", + "basepath": "", + "proxyUrl": "", + "baseOptions": "", + "allowImageUploads": true, + "imageResolution": "low", + "reasoningEffort": "medium" + }, + "outputAnchors": [ + { + "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", + "name": "chatOpenAI", + "label": "ChatOpenAI", + "description": "Wrapper around OpenAI large language models that use the Chat endpoint", + "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" + } + ], + "outputs": {}, + "selected": false + }, + "selected": false, + "positionAbsolute": { + "x": 97.01321406237057, + "y": 63.67664262280914 + }, + "dragging": false + }, + { + "id": "stickyNote_0", + "position": { + "x": 1197.3578961103253, + "y": 117.43214592301385 + }, + "type": "stickyNote", + "data": { + "id": "stickyNote_0", + "label": "Sticky Note", + "version": 2, + "name": "stickyNote", + "type": "StickyNote", + "baseClasses": ["StickyNote"], + "tags": ["Utilities"], + "category": "Utilities", + "description": "Add a sticky note", + "inputParams": [ + { + "label": "", + "name": "note", + "type": "string", + "rows": 1, + "placeholder": "Type something here", + "optional": true, + "id": "stickyNote_0-input-note-string" + } + ], + "inputAnchors": [], + "inputs": { + "note": "LLM has to be function calling compatible" + }, + "outputAnchors": [ + { + "id": "stickyNote_0-output-stickyNote-StickyNote", + "name": "stickyNote", + "label": "StickyNote", + "description": "Add a sticky note", + "type": "StickyNote" + } + ], + "outputs": {}, + "selected": false + }, + "width": 300, + "height": 62, + "selected": false, + "positionAbsolute": { + "x": 1197.3578961103253, + "y": 117.43214592301385 + }, + "dragging": false + }, + { + "id": "toolAgent_0", + "position": { + "x": 1200.6756893536506, + "y": 208.18578883272318 + }, + "type": "customNode", + "data": { + "id": "toolAgent_0", + "label": "Tool Agent", + "version": 2, + "name": "toolAgent", + "type": "AgentExecutor", + "baseClasses": ["AgentExecutor", "BaseChain", "Runnable"], + "category": "Agents", + "description": "Agent that uses Function Calling to pick the tools and args to call", + "inputParams": [ + { + "label": "System Message", + "name": "systemMessage", + "type": "string", + "default": "You are a helpful AI assistant.", + "description": "If Chat Prompt Template is provided, this will be ignored", + "rows": 4, + "optional": true, + "additionalParams": true, + "id": "toolAgent_0-input-systemMessage-string", + "display": true + }, + { + "label": "Max Iterations", + "name": "maxIterations", + "type": "number", + "optional": true, + "additionalParams": true, + "id": "toolAgent_0-input-maxIterations-number", + "display": true + }, + { + "label": "Enable Detailed Streaming", + "name": "enableDetailedStreaming", + "type": "boolean", + "default": false, + "description": "Stream detailed intermediate steps during agent execution", + "optional": true, + "additionalParams": true, + "id": "toolAgent_0-input-enableDetailedStreaming-boolean", + "display": true + } + ], + "inputAnchors": [ + { + "label": "Tools", + "name": "tools", + "type": "Tool", + "list": true, + "id": "toolAgent_0-input-tools-Tool", + "display": true + }, + { + "label": "Memory", + "name": "memory", + "type": "BaseChatMemory", + "id": "toolAgent_0-input-memory-BaseChatMemory", + "display": true + }, + { + "label": "Tool Calling Chat Model", + "name": "model", + "type": "BaseChatModel", + "description": "Only compatible with models that are capable of function calling: ChatOpenAI, ChatMistral, ChatAnthropic, ChatGoogleGenerativeAI, ChatVertexAI, GroqChat", + "id": "toolAgent_0-input-model-BaseChatModel", + "display": true + }, + { + "label": "Chat Prompt Template", + "name": "chatPromptTemplate", + "type": "ChatPromptTemplate", + "description": "Override existing prompt with Chat Prompt Template. Human Message must includes {input} variable", + "optional": true, + "id": "toolAgent_0-input-chatPromptTemplate-ChatPromptTemplate", + "display": true + }, + { + "label": "Input Moderation", + "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", + "name": "inputModeration", + "type": "Moderation", + "optional": true, + "list": true, + "id": "toolAgent_0-input-inputModeration-Moderation", + "display": true + } + ], + "inputs": { + "tools": ["{{calculator_1.data.instance}}", "{{serpAPI_0.data.instance}}"], + "memory": "{{bufferMemory_1.data.instance}}", + "model": "{{chatOpenAI_0.data.instance}}", + "chatPromptTemplate": "", + "systemMessage": "You are a helpful AI assistant.", + "inputModeration": "", + "maxIterations": "", + "enableDetailedStreaming": "" + }, + "outputAnchors": [ + { + "id": "toolAgent_0-output-toolAgent-AgentExecutor|BaseChain|Runnable", + "name": "toolAgent", + "label": "AgentExecutor", + "description": "Agent that uses Function Calling to pick the tools and args to call", + "type": "AgentExecutor | BaseChain | Runnable" + } + ], + "outputs": {}, + "selected": false + }, + "width": 300, + "height": 492, + "selected": false, + "positionAbsolute": { + "x": 1200.6756893536506, + "y": 208.18578883272318 + }, + "dragging": false + } + ], + "edges": [ + { + "source": "calculator_1", + "sourceHandle": "calculator_1-output-calculator-Calculator|Tool|StructuredTool|BaseLangChain", + "target": "toolAgent_0", + "targetHandle": "toolAgent_0-input-tools-Tool", + "type": "buttonedge", + "id": "calculator_1-calculator_1-output-calculator-Calculator|Tool|StructuredTool|BaseLangChain-toolAgent_0-toolAgent_0-input-tools-Tool" + }, + { + "source": "serpAPI_0", + "sourceHandle": "serpAPI_0-output-serpAPI-SerpAPI|Tool|StructuredTool", + "target": "toolAgent_0", + "targetHandle": "toolAgent_0-input-tools-Tool", + "type": "buttonedge", + "id": "serpAPI_0-serpAPI_0-output-serpAPI-SerpAPI|Tool|StructuredTool-toolAgent_0-toolAgent_0-input-tools-Tool" + }, + { + "source": "chatOpenAI_0", + "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", + "target": "toolAgent_0", + "targetHandle": "toolAgent_0-input-model-BaseChatModel", + "type": "buttonedge", + "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-toolAgent_0-toolAgent_0-input-model-BaseChatModel" + }, + { + "source": "bufferMemory_1", + "sourceHandle": "bufferMemory_1-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory", + "target": "toolAgent_0", + "targetHandle": "toolAgent_0-input-memory-BaseChatMemory", + "type": "buttonedge", + "id": "bufferMemory_1-bufferMemory_1-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory-toolAgent_0-toolAgent_0-input-memory-BaseChatMemory" + } + ] +} diff --git a/packages/server/marketplaces/chatflows/Transcript Summarization.json b/packages/server/marketplaces/chatflows/Transcript Summarization.json deleted file mode 100644 index b8e8fd25..00000000 --- a/packages/server/marketplaces/chatflows/Transcript Summarization.json +++ /dev/null @@ -1,512 +0,0 @@ -{ - "description": "Use Anthropic Claude with 200k context window to ingest whole document for summarization", - "framework": ["Langchain"], - "usecases": ["Summarization"], - "nodes": [ - { - "width": 300, - "height": 253, - "id": "bufferMemory_0", - "position": { - "x": 240.5161028076149, - "y": 165.35849026339048 - }, - "type": "customNode", - "data": { - "id": "bufferMemory_0", - "label": "Buffer Memory", - "version": 2, - "name": "bufferMemory", - "type": "BufferMemory", - "baseClasses": ["BufferMemory", "BaseChatMemory", "BaseMemory"], - "category": "Memory", - "description": "Retrieve chat messages stored in database", - "inputParams": [ - { - "label": "Session Id", - "name": "sessionId", - "type": "string", - "description": "If not specified, a random id will be used. Learn more", - "default": "", - "additionalParams": true, - "optional": true, - "id": "bufferMemory_0-input-sessionId-string" - }, - { - "label": "Memory Key", - "name": "memoryKey", - "type": "string", - "default": "chat_history", - "additionalParams": true, - "id": "bufferMemory_0-input-memoryKey-string" - } - ], - "inputAnchors": [], - "inputs": { - "sessionId": "", - "memoryKey": "chat_history" - }, - "outputAnchors": [ - { - "id": "bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory", - "name": "bufferMemory", - "label": "BufferMemory", - "type": "BufferMemory | BaseChatMemory | BaseMemory" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 240.5161028076149, - "y": 165.35849026339048 - }, - "dragging": false - }, - { - "width": 300, - "height": 435, - "id": "conversationChain_0", - "position": { - "x": 958.9887390513221, - "y": 318.8734467468765 - }, - "type": "customNode", - "data": { - "id": "conversationChain_0", - "label": "Conversation Chain", - "version": 3, - "name": "conversationChain", - "type": "ConversationChain", - "baseClasses": ["ConversationChain", "LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chat models specific conversational chain with memory", - "inputParams": [ - { - "label": "System Message", - "name": "systemMessagePrompt", - "type": "string", - "rows": 4, - "description": "If Chat Prompt Template is provided, this will be ignored", - "additionalParams": true, - "optional": true, - "default": "The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.", - "placeholder": "The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.", - "id": "conversationChain_0-input-systemMessagePrompt-string" - } - ], - "inputAnchors": [ - { - "label": "Chat Model", - "name": "model", - "type": "BaseChatModel", - "id": "conversationChain_0-input-model-BaseChatModel" - }, - { - "label": "Memory", - "name": "memory", - "type": "BaseMemory", - "id": "conversationChain_0-input-memory-BaseMemory" - }, - { - "label": "Chat Prompt Template", - "name": "chatPromptTemplate", - "type": "ChatPromptTemplate", - "description": "Override existing prompt with Chat Prompt Template. Human Message must includes {input} variable", - "optional": true, - "id": "conversationChain_0-input-chatPromptTemplate-ChatPromptTemplate" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "conversationChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "inputModeration": "", - "model": "{{chatAnthropic_0.data.instance}}", - "memory": "{{bufferMemory_0.data.instance}}", - "chatPromptTemplate": "{{chatPromptTemplate_0.data.instance}}", - "systemMessagePrompt": "The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know." - }, - "outputAnchors": [ - { - "id": "conversationChain_0-output-conversationChain-ConversationChain|LLMChain|BaseChain|Runnable", - "name": "conversationChain", - "label": "ConversationChain", - "type": "ConversationChain | LLMChain | BaseChain | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 958.9887390513221, - "y": 318.8734467468765 - }, - "dragging": false - }, - { - "width": 300, - "height": 670, - "id": "chatAnthropic_0", - "position": { - "x": 585.3308245972187, - "y": -116.32789506560908 - }, - "type": "customNode", - "data": { - "id": "chatAnthropic_0", - "label": "ChatAnthropic", - "version": 6, - "name": "chatAnthropic", - "type": "ChatAnthropic", - "baseClasses": ["ChatAnthropic", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around ChatAnthropic large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["anthropicApi"], - "id": "chatAnthropic_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "claude-3-haiku", - "id": "chatAnthropic_0-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatAnthropic_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokensToSample", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatAnthropic_0-input-maxTokensToSample-number" - }, - { - "label": "Top P", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatAnthropic_0-input-topP-number" - }, - { - "label": "Top K", - "name": "topK", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatAnthropic_0-input-topK-number" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses claude-3-* models when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatAnthropic_0-input-allowImageUploads-boolean" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatAnthropic_0-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "claude-3-haiku-20240307", - "temperature": 0.9, - "maxTokensToSample": "", - "topP": "", - "topK": "", - "allowImageUploads": true - }, - "outputAnchors": [ - { - "id": "chatAnthropic_0-output-chatAnthropic-ChatAnthropic|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatAnthropic", - "label": "ChatAnthropic", - "type": "ChatAnthropic | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 585.3308245972187, - "y": -116.32789506560908 - }, - "dragging": false - }, - { - "width": 300, - "height": 690, - "id": "chatPromptTemplate_0", - "position": { - "x": -106.44189698270114, - "y": 20.133956087516538 - }, - "type": "customNode", - "data": { - "id": "chatPromptTemplate_0", - "label": "Chat Prompt Template", - "version": 1, - "name": "chatPromptTemplate", - "type": "ChatPromptTemplate", - "baseClasses": ["ChatPromptTemplate", "BaseChatPromptTemplate", "BasePromptTemplate", "Runnable"], - "category": "Prompts", - "description": "Schema to represent a chat prompt", - "inputParams": [ - { - "label": "System Message", - "name": "systemMessagePrompt", - "type": "string", - "rows": 4, - "placeholder": "You are a helpful assistant that translates {input_language} to {output_language}.", - "id": "chatPromptTemplate_0-input-systemMessagePrompt-string" - }, - { - "label": "Human Message", - "name": "humanMessagePrompt", - "type": "string", - "rows": 4, - "placeholder": "{text}", - "id": "chatPromptTemplate_0-input-humanMessagePrompt-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "chatPromptTemplate_0-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "systemMessagePrompt": "Act as an expert copywriter specializing in content optimization for SEO. Your task is to take a given YouTube transcript and transform it into a well-structured and engaging article. Your objectives are as follows:\n\nContent Transformation: Begin by thoroughly reading the provided YouTube transcript. Understand the main ideas, key points, and the overall message conveyed.\n\nSentence Structure: While rephrasing the content, pay careful attention to sentence structure. Ensure that the article flows logically and coherently.\n\nKeyword Identification: Identify the main keyword or phrase from the transcript. It's crucial to determine the primary topic that the YouTube video discusses.\n\nKeyword Integration: Incorporate the identified keyword naturally throughout the article. Use it in headings, subheadings, and within the body text. However, avoid overuse or keyword stuffing, as this can negatively affect SEO.\n\nUnique Content: Your goal is to make the article 100% unique. Avoid copying sentences directly from the transcript. Rewrite the content in your own words while retaining the original message and meaning.\n\nSEO Friendliness: Craft the article with SEO best practices in mind. This includes optimizing meta tags (title and meta description), using header tags appropriately, and maintaining an appropriate keyword density.\n\nEngaging and Informative: Ensure that the article is engaging and informative for the reader. It should provide value and insight on the topic discussed in the YouTube video.\n\nProofreading: Proofread the article for grammar, spelling, and punctuation errors. Ensure it is free of any mistakes that could detract from its quality.\n\nBy following these guidelines, create a well-optimized, unique, and informative article that would rank well in search engine results and engage readers effectively.\n\nTranscript:{transcript}", - "humanMessagePrompt": "{input}", - "promptValues": "{\"input\":\"{{question}}\",\"transcript\":\"{{plainText_0.data.instance}}\"}" - }, - "outputAnchors": [ - { - "id": "chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate|Runnable", - "name": "chatPromptTemplate", - "label": "ChatPromptTemplate", - "type": "ChatPromptTemplate | BaseChatPromptTemplate | BasePromptTemplate | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": -106.44189698270114, - "y": 20.133956087516538 - }, - "dragging": false - }, - { - "width": 300, - "height": 487, - "id": "plainText_0", - "position": { - "x": -487.7511991135089, - "y": 77.83838996645807 - }, - "type": "customNode", - "data": { - "id": "plainText_0", - "label": "Plain Text", - "version": 2, - "name": "plainText", - "type": "Document", - "baseClasses": ["Document"], - "category": "Document Loaders", - "description": "Load data from plain text", - "inputParams": [ - { - "label": "Text", - "name": "text", - "type": "string", - "rows": 4, - "placeholder": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua...", - "id": "plainText_0-input-text-string" - }, - { - "label": "Metadata", - "name": "metadata", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "plainText_0-input-metadata-json" - } - ], - "inputAnchors": [ - { - "label": "Text Splitter", - "name": "textSplitter", - "type": "TextSplitter", - "optional": true, - "id": "plainText_0-input-textSplitter-TextSplitter" - } - ], - "inputs": { - "text": "\n\n00:00 - It starts by showing [this question](https://stackoverflow.com/questions/32191198/i-would-like-to-split-this-into-a-list-but-i-dont-know-how-in-python) and reading it out loud\n\n0:00 - \"I have this string. I want to split it on the pipe, but I don't know how. I don't want to split it at the white-space, only at the pipe. Is this possible?\"\n\n0:10 - The comments below the question are presented and read out loud:\n\n> Did you try Googling _anything_ about the `split()` method?\n\n> Welcome to Stack Overflow! You seem to be asking for someone to write some code for you. Stack Overflow is a question and answer site, not a code-writing service. Please see here to learn how to write effective questions.\n\n0:23 - \"Whatever happened to Stack Overflow? How did we end up in a place where we not only get rude and snarky comments but we also get robotic-like responses from real people from valid questions?\"\n\n0:36 - \"This is not a rare scenario. This has become the norm on Stack Overflow. And I just have one question. How did we end up here?\"\n\n0:46 - \"My name is Gabe. And today we're going to look at some of the key factors that resulted in the cesspool that is Stack Overflow Q&A today. I'll also explore some approaches that may solve the problems we face, so that developers can just share information without fear of reproach.\" \n\n(In big letters, \"The Egotistical Mods of Stack Overflow\")\n\n1:08 - Title: The Stack Overflow Age\n\n1:12 - \"Let's go back in time to 2008. NASA's unmanned spacecraft Phoenix becomes the first to land on the northern polar region of Mars, Google Chrome is first released, the stock market plunges across the globe, and a little-known Stack Overflow comes into existence. Stack Overflow was created by Joel Spolsky and Jeff Atwood to address an issue that was apparent in the mid to late 2000s. The issue was that programmers had no way to easily share knowledge about difficult problems. There was Usenet which became obsolete once the World Wide Web became popular, then there was Experts Exchange where developers could share questions and answers. This had a myriad of problems the foremost being it was a paid serve. Joel wanted a free website that could replace Experts Exchange and earn money while doubling as a job listing board. He know somebody would do it eventually, so he waited.... and waited... and he waited... then one day, Jeff Atwood came to him for advice on blogging and Joel simply responded \"I've got a better idea instead\".\"\n\n2:12 - \"The Stack Overflow experiment went extraordinarily well. It was based on a gamification system similar to Reddit and other sites where users could upvote good questions and good answers. Once you got a certain amount of reputation you were granted more privileges to the site. These privileges included editing questions, closing questions and reopening questions. This means that poor questions are dealt with quickly and good answers rank higher. This worked great for moderation in the short term. However, it led to the problems we see today.\n\n2:28 - Title: \"The Problems\"\n\n2:42 - \"OK. So let's review real quickly how do users gain privilege? Well, they gain privilege by answering questions. What can you do with the privilege? You can answer questions, you can close questions, you can edit questions and you can reopen questions. OK. Well all that makes sense, well, what happens if you ask and somebody decides to close it? Well, you could reopen it but wait a second... you need the privilege to reopen it, and the privilege you don't have because... you're a new user.\"\n\n3:10 - \"OK well, what if somebody is bullying you in the comments? Well, you flag the comment OK, and then the flagged comment goes to... the moderators.\"\n\n3:19 - \"So let's just take a look at some questions on Stack Overflow right now. There's this user who asks:\"\n\n3:24 - A question is show, content verbatim save for the link, redacted in this transcript:\n\n> ### What technology was this website been built with?\n>\n> I apologise in advance if this question is not allowed here.\n>\n> Do you know what technology has been used to build this website?\n>\n> [REDACTED]\n> \n> Viewing the dev console and source has offered me no clues!\n\n(asked Nov 17 '16 at 18:34)\n\n3:31 - \"Now, I think this is a valid question. Programmers build websites using so many different technologies, it's reasonable to ask if anyone knows what a particular site used to build it. Well, the Stack Overflow users, they have a different thought. The first one says:\"\n\n> Seems like you already knew questions like this are off-topic. -- Nov 17 '16 at 18:36\n\n3:49 - \"And then this person says:\"\n\n> I see quite a bit of information in the dev. tools. -- Nov 17 '16 at 18:36\n\n\"The implication being, 'why can _you_ see what the devtools show _me_?'\nThis next person says:\"\n\n> Really? The console offered nothing? To me, it yelled out pixijs.com... -- Nov 17 '16 at 18:37\n\n4:06 - \"and this user gave a very helpful answer, that it's:\"\n\n> Magic, naturally. -- Nov 17 '16 at 18:38\n\n\"And then finally somebody just says:\"\n\n> I confirm it's pixijs -- Nov 17 '16 at 18:39\n\n\"It's pixijs, that's what they used. And the poor user simply says thanks and then leaves with their tail between their legs.\"\n\n> My apologies :( Thanks for the link -- Nov 17 '16 at 18:39\n\n4:21 - \"What's wrong with these people? Why is it so difficult to just say it's pixijs?\"\n\n4:27 - \"All right so the next question is pretty technical, but an experienced programmer should be able to help out. So this person asked:\"\n\n> ### Initialization of a constant reference with a number\n>\n> What is the meaning of the following line? Why is this allowed as 0 is an r-value and not a variable name? What is the significance of `const` in this statement?\n>\n> ```c++\n> const int &x = 0;\n> ```\n\n(asked May 15 '18 at 21:35) https://stackoverflow.com/q/50359481\n\n(Note: as presented in the video, the question was not closed and had a score of -10)\n\n4:41 - \"Aand the responses, so... first person says:\"\n\n> Homework? And what does your C++ textbook have to say on the subject? -- May 15 '18 at 21:36 (now deleted)\n\n\"And the next person, very helpfully, says:\"\n\n> Just read a [good book]. -- May 15 18' at 21:38 (now deleted)\n\n\"And then, 'here, this link has a similar question', which may or may not have been helpful at all\":\n\n> Similar: -- May 15 18' at 21:39\n\n4:56 - \"Now, I was actually curious about what this question... was, like what the answer to this was, because I didn't even know what it was. I code in C++ pretty regularly and did not know the meaning of this, I'd never seen this syntax, and didn't even know it was valid code. And this poor guy was downvoted 10 times, why? Because he had the audacity to ask a question. OK? OK.\n\n5:20 - \"So, he finally finds an answer and then he posts it to the website. Uh, the answer gets downvoted, so if anybody else is looking for something similar, they can't find it. And I was actually curious about this, like I had never seen this before, and yet if I ever were searching for it I probably wouldn't find it because Google is now gonna rank this low, since it was downvoted.\n\n5:39 - \"This next user asks:\"\n\n> ### What is e in e.preventDefault()\n>\n> I am not able to understand the parameter 'e' which is passed to prevent the Default Action in JavaScript\n> \n> ```javascript\n> document.getElementById('submit').addEventListener('click', calculate, false);\n> function calculate(e){\n> e.preventDefault():\n> }\n> ```\n\n(asked Sep 14 '17 at 9:57) https://stackoverflow.com/q/46216042\n\n5:49 - \"Now, to an experienced programmer this is pretty obvious. However, if you don't program and you've never seen this or you're new to programming, this is a completely valid question. The responses:\"\n\n> e is the event. -- Sep 14 '17 at 9:58\n\n6:02 - \"Well, that's actually a pretty tame response but it provides absolutely no information.\"\n\n(more unmentioned comments are displayed, as seen below)\n\n> e represents the event which has a lot of properties. -- Sep 14 '17 at 9:58\n\n> You can read about the [click event here] -- Sep 14 '17 at 10:02\n\n> When the JavaScript engine calls the callback you provided, it passes an Event object. You gain access to that passed object by giving the function a parameter. You don't have to call it e; you can use any valid variable name you want. Your confusion probably arises from the fact that you provide a function called by JS, instead of the other way around. -- Sep 14 '17 at 10:03\n\n6:07 - \"Then this lovely gentleman says:\"\n\n> \"This question shows zero research effort. Aside from the fact you get that answer by literally typing your title into google, did you try anything, like `console.log(e)` on different element bindings to see what it might be?\" -- Sep 14 '17 at 10:04 (now deleted)\n\n6:22 - \"What is wrong with these people, they seem to have forgotten that Stack Overflow is a Q&A site! How dare this user ask a question! On a Q&A site!\"\n\n6:31 - \"This user says:\"\n\n> I am learning coding c++ in Unreal Engine, I got this syntax I don't really get:\n> \n> ```c++\n> class USphereComponent* ProxSphere;\n> ```\n>\n> I think this means create a class, but this class is a pointer?\n> \n> But the result is just create an object called ProxSphere from an existing class USphereComponent.\n> \n> Could anyone explain how this syntax actually means and it's usage?\n\n(asked Feb 6 '16 at 17:51) https://stackoverflow.com/questions/35244342\n\n(At the time of writing, the question had received a score inflation also caused by the extra attention from the video (+13, -9))\n\n6:42 - \"The responses:\"\n\n> Please pick up a text book and learn C++ systematically. -- Feb 6 '16 at 17:52 (now deleted)\n\n\"Um, I'm sorry? This is a Q&A site.\"\n\n> This is a class pointer declaration, no more, no less. -- Feb 6 '16 at 17:52\n\n6:53 - \"Ah, that makes it perfectly clear, how did I not see that before. Just in case you're wondering, that is sarcasm, that is not clear at all! Once again, this is an example of a problem I've never seen before, and I program in C++ almost daily. This user thankfully provided a clear and concise explanation, but why did all those other users feel the need to waste time out of their day to berate someone who had the audacity to ask a question?\"\n\n7:23 - \"This next question's answer gives us a little window into the moderator's brains. Warning, it's a scary place. This users asks:\"\n\n> ### How to answer a closed question?\n>\n> This [question](https://stackoverflow.com/questions/61054657/input-twice-to-pass-the-condition?noredirect=1#comment108031699_61054657) was closed yesterday for obvious reasons. One important function in question which answers were really depending on that wasn't in question. Then after the question was closed, OP left a comment that they had added the function which makes the question very clear.\n> \n> How can I answer this question? Should I create a chat room?\n\n(asked April 7 '20 at 13:21) Meta https://meta.stackoverflow.com/questions/396379\n\n 7:43 - \"Now, this is the crux of the problem with Stack Overflow. Closed questions are sort of left in a limbo state. They're closed so they can't be answered. You have to edit it to be able to answer it, but we've already talked about the problems that come with editing it and trying to get your question reopened. Hint hint, it requires reputation, which most people don't have.\"\n\n8:02 - \"Fortunately, a moderator gives us an answer to this question. He says:\"\n\n> ### Edit the Question to include the comment, and then vote to reopen it.\n\n\"Oh, OK so, uh, you just edit it and then you have to vote to reopen it, so even if the question is fixed, you can't reopen it at all.\"\n\n8:18 - \"And then he puts in bold:\"\n\n> **Do not open a chat room or answer in comments or otherwise work around the closing.**\n\n\"'Cuz... how dare somebody try to help some other random person on the internet.\"\n\n8:29 - Title: \"Closed Questions\"\n\n8:29 - \"OK let's change it up a bit, let's look at some questions that were closed, but lots of people disagreed with that closing.\"\n\n8:36 - \"This question says:\"\n\n> ### The Use of Multiple JFrames: Good or Bad Practice?\n>\n> I'm developing an application which displays images, and plays sounds from a database. I'm trying to decide whether or not to use a separate JFrame to add images to the database from the GUI.\n>\n> I'm just wondering whether it is good practice to use multiple JFrame windows?\n\n(asked Mar 4 '12 at 11:53) https://stackoverflow.com/questions/9554636\n\n\"Well, why was this closed? Because... it is opinion based.\"\n\n8:46 - \"Stack Overflow moderators, they hate opinions, OK? And why do they hate opinions? Well... nobody really knows, heheh... and opinions are kinda tricky because you can't tell if a question's subjective or objective, there's kind of a blurry line between those two. And who gets to decide whether it's subjective of objective? Well, the moderators.\"\n\n9:10 - \"And in the responses we can see people say this question has become more valuable than they ever thought it could. Well, I guess the mods just got this one wrong.\"\n\n9:18 - \"Oops! It looks like they got this one wrong too. This question has 557 upvotes! That's a lot on Stack Overflow, where questions typically get only 5 or 6 upvotes. Why was it closed? Well, uh, we don't know. It was closed because a mod decided it needed to be.\"\n\n> ### Does anyone have benchmarks (code & results) comparing performance of Android apps written in Xamarin C# and Java?\n\n(asked Mar 4 '12 at 11:53) https://stackoverflow.com/questions/17134522\n\n9:34 - \"Surely this was just another one-off mistake, right? Wait. The mods messed up again? \"\n\n> ### Seeking useful Eclipse Java code templates \n\n(asked Jun 22 '09 at 19:00) https://stackoverflow.com/questions/1028858\n\n\"This question was closed because... it... wasn't focused enough. Well, it got 518 upvotes, so clearly some people, at least half a thousand of them, though it was focused enough.\"\n\n9:52 - \"I'm beginning to see a pattern here. 371 upvotes? Well, it's closed. Why? Because it's an opinion.\"\n\n> ### What is the best way to implement constants in Java?\n\n(asked Sep 15 '08 at 19:39, history locked) https://stackoverflow.com/q/66066\n\n9:56 - \"Another opinion? How dare these programmers ask an opinionated question.\"\n\n> ### Best XML parser for Java?\n\n(asked Dec 17 '08 at 6:52) https://stackoverflow.com/questions/373833\n\n10:01 - \"Finally someone was fed up enough and said:\n\n> +220 and not constructive. Clearly moderators and users have different perspectives on what is constructive. -- Jun 9 '14 at 6:40\n\n10:10 - \"I agree, random user. I completely, wholeheartedly agree.\"\n\n10:15 - \"Another opinion! Man, these stupid programmers can't stop asking subjective questions, can they!?\"\n\n> ### C++ code file extension? What is the difference between .cc and .cpp?\n\n(asked Oct 9 '09 at 17:23) https://stackoverflow.com/questions/1545080\n\n10:20 - \"These moderators, pff... they have such a difficult life.\"\n\n10:23 - \"This question was closed because, well, we actually don't know why it was closed. Eh eh.\"\n\n> ### Why have header files and .cpp files?\n\n(asked Dec 2 '08 at 13:17) https://stackoverflow.com/q/333889\n\n10:28 - \"Unfocused question. Closed! Nice. Moving on...\"\n\n> ### Calling C/C++ from Python?\n\n(asked Sep 28 '08 at 5:34) https://stackoverflow.com/questions/145270\n\n10:32 - \"More opinions. Moving on...\"\n\n> ### Case-insensitive string comparison in C++\n\n(asked Aug 14 '08 at 20:01) https://stackoverflow.com/q/11635\n\n10:34 - \"You know... I just don't like this guy's name. Let's close this one and move on.\"\n\n> ### Do you (really) write exception safe code?\n\n(asked Dec 5 '09 at 19:48) https://stackoverflow.com/questions/1853243\n\n10:38 - \"Another opinion! Oh wait, 3000 people actually wanted to know the answer to this one.\"\n\n> ### What is the best way to iterate over a dictionary?\n\n(not found via search, must have been deleted)\n\n10:42 - \"Maybe... I'm not such a good moderator. Nah, hah, these people just don't know an opinion when it smacks them in the face.\"\n\n10:54 - Title: \"Conclusion\"\n\n10:59 - \"Unfortunately I have so many more examples of this. If you want to see examples of this just click the link in the description and you can see up to 500 more questions that are just like the ones I just showed you.\"\n\nThe link: https://stackoverflow.com/search?q=closed%3A1+duplicate%3A0\n\n11:10 - \"Even though there are only 500 questions there, there's probably thousands of questions that will never see the light of day because of the rigged system that we already talked about that is in place.\"\n\n11:23 - \"Stack Overflow has a problem. I wish it didn't, because it's helped me and so many other programmers over the past decade. However, I think it's reaching its lifetime. It's going to remain a valuable resource for decades to come, but it's no longer gaining value. If you ask programmers who have asked questions on Stack Overflow, I bet you they got their own horror stories to tell. Not only that, but they'll talk about how they now go to Discord servers or Reddit, Quora, or anywhere else except Stack Overflow because, nobody likes to be berated for absolutely no reason. Maybe Stack Overflow will notice this problem. The real problem. And fix this.\"\n\n12:00 - \"Anyways, that is all I have for today. I hope you learned a little bit about the cesspool that is Stack Overflow.\"", - "textSplitter": "", - "metadata": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "plainText_0-output-document-Document|json", - "name": "document", - "label": "Document", - "type": "Document | json" - }, - { - "id": "plainText_0-output-text-string|json", - "name": "text", - "label": "Text", - "type": "string | json" - } - ], - "default": "document" - } - ], - "outputs": { - "output": "text" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": -487.7511991135089, - "y": 77.83838996645807 - }, - "dragging": false - }, - { - "id": "stickyNote_0", - "position": { - "x": 956.2443072079327, - "y": 19.62362357631281 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_0", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_0-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "With large context size LLM like Anthropic and Gemini, we can shovel whole content into LLM without breaking into chunks.\n\nThis is useful when you need to do summarization or translation word by word without losing any context.\n\nIn this example, we give a piece of Youtube transcript and a prompt for summarization.\n\nExample question:\nCan you summarize the key points?" - }, - "outputAnchors": [ - { - "id": "stickyNote_0-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 284, - "selected": false, - "positionAbsolute": { - "x": 956.2443072079327, - "y": 19.62362357631281 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "bufferMemory_0", - "sourceHandle": "bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory", - "target": "conversationChain_0", - "targetHandle": "conversationChain_0-input-memory-BaseMemory", - "type": "buttonedge", - "id": "bufferMemory_0-bufferMemory_0-output-bufferMemory-BufferMemory|BaseChatMemory|BaseMemory-conversationChain_0-conversationChain_0-input-memory-BaseMemory" - }, - { - "source": "chatAnthropic_0", - "sourceHandle": "chatAnthropic_0-output-chatAnthropic-ChatAnthropic|BaseChatModel|BaseLanguageModel|Runnable", - "target": "conversationChain_0", - "targetHandle": "conversationChain_0-input-model-BaseChatModel", - "type": "buttonedge", - "id": "chatAnthropic_0-chatAnthropic_0-output-chatAnthropic-ChatAnthropic|BaseChatModel|BaseLanguageModel|Runnable-conversationChain_0-conversationChain_0-input-model-BaseChatModel" - }, - { - "source": "plainText_0", - "sourceHandle": "plainText_0-output-text-string|json", - "target": "chatPromptTemplate_0", - "targetHandle": "chatPromptTemplate_0-input-promptValues-json", - "type": "buttonedge", - "id": "plainText_0-plainText_0-output-text-string|json-chatPromptTemplate_0-chatPromptTemplate_0-input-promptValues-json" - }, - { - "source": "chatPromptTemplate_0", - "sourceHandle": "chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate|Runnable", - "target": "conversationChain_0", - "targetHandle": "conversationChain_0-input-chatPromptTemplate-ChatPromptTemplate", - "type": "buttonedge", - "id": "chatPromptTemplate_0-chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate|Runnable-conversationChain_0-conversationChain_0-input-chatPromptTemplate-ChatPromptTemplate" - } - ] -} diff --git a/packages/server/marketplaces/chatflows/Translator.json b/packages/server/marketplaces/chatflows/Translator.json deleted file mode 100644 index 9ec3285d..00000000 --- a/packages/server/marketplaces/chatflows/Translator.json +++ /dev/null @@ -1,424 +0,0 @@ -{ - "description": "Language translation using LLM Chain with a Chat Prompt Template and Chat Model", - "usecases": ["Basic"], - "framework": ["Langchain"], - "nodes": [ - { - "width": 300, - "height": 690, - "id": "chatPromptTemplate_0", - "position": { - "x": 88.10922294721732, - "y": 373.4354021348812 - }, - "type": "customNode", - "data": { - "id": "chatPromptTemplate_0", - "label": "Chat Prompt Template", - "version": 1, - "name": "chatPromptTemplate", - "type": "ChatPromptTemplate", - "baseClasses": ["ChatPromptTemplate", "BaseChatPromptTemplate", "BasePromptTemplate"], - "category": "Prompts", - "description": "Schema to represent a chat prompt", - "inputParams": [ - { - "label": "System Message", - "name": "systemMessagePrompt", - "type": "string", - "rows": 4, - "placeholder": "You are a helpful assistant that translates {input_language} to {output_language}.", - "id": "chatPromptTemplate_0-input-systemMessagePrompt-string" - }, - { - "label": "Human Message", - "name": "humanMessagePrompt", - "type": "string", - "rows": 4, - "placeholder": "{text}", - "id": "chatPromptTemplate_0-input-humanMessagePrompt-string" - }, - { - "label": "Format Prompt Values", - "name": "promptValues", - "type": "json", - "optional": true, - "acceptVariable": true, - "list": true, - "id": "chatPromptTemplate_0-input-promptValues-json" - } - ], - "inputAnchors": [], - "inputs": { - "systemMessagePrompt": "You are a helpful assistant that translates {input_language} to {output_language}.", - "humanMessagePrompt": "{text}", - "promptValues": "{\"input_language\":\"English\",\"output_language\":\"French\",\"text\":\"\"}" - }, - "outputAnchors": [ - { - "id": "chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate", - "name": "chatPromptTemplate", - "label": "ChatPromptTemplate", - "type": "ChatPromptTemplate | BaseChatPromptTemplate | BasePromptTemplate" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 88.10922294721732, - "y": 373.4354021348812 - }, - "dragging": false - }, - { - "width": 300, - "height": 670, - "id": "chatOpenAI_0", - "position": { - "x": 423.0077090865524, - "y": 380.66673510213775 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_0", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_0-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "default": 0.9, - "optional": true, - "id": "chatOpenAI_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_0-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_0-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_0-input-cache-BaseCache" - } - ], - "inputs": { - "modelName": "gpt-3.5-turbo", - "temperature": "0", - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 423.0077090865524, - "y": 380.66673510213775 - }, - "dragging": false - }, - { - "width": 300, - "height": 508, - "id": "llmChain_0", - "position": { - "x": 774.5069894501554, - "y": 480.02655553818863 - }, - "type": "customNode", - "data": { - "id": "llmChain_0", - "label": "LLM Chain", - "version": 3, - "name": "llmChain", - "type": "LLMChain", - "baseClasses": ["LLMChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Chain to run queries against LLMs", - "inputParams": [ - { - "label": "Chain Name", - "name": "chainName", - "type": "string", - "placeholder": "Name Your Chain", - "optional": true, - "id": "llmChain_0-input-chainName-string" - } - ], - "inputAnchors": [ - { - "label": "Language Model", - "name": "model", - "type": "BaseLanguageModel", - "id": "llmChain_0-input-model-BaseLanguageModel" - }, - { - "label": "Prompt", - "name": "prompt", - "type": "BasePromptTemplate", - "id": "llmChain_0-input-prompt-BasePromptTemplate" - }, - { - "label": "Output Parser", - "name": "outputParser", - "type": "BaseLLMOutputParser", - "optional": true, - "id": "llmChain_0-input-outputParser-BaseLLMOutputParser" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "llmChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "model": "{{chatOpenAI_0.data.instance}}", - "prompt": "{{chatPromptTemplate_0.data.instance}}", - "outputParser": "", - "chainName": "Language Translation", - "inputModeration": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "llmChain_0-output-llmChain-LLMChain|BaseChain|Runnable", - "name": "llmChain", - "label": "LLM Chain", - "type": "LLMChain | BaseChain | Runnable" - }, - { - "id": "llmChain_0-output-outputPrediction-string|json", - "name": "outputPrediction", - "label": "Output Prediction", - "type": "string | json" - } - ], - "default": "llmChain" - } - ], - "outputs": { - "output": "llmChain" - }, - "selected": false - }, - "selected": false, - "dragging": false, - "positionAbsolute": { - "x": 774.5069894501554, - "y": 480.02655553818863 - } - }, - { - "id": "stickyNote_0", - "position": { - "x": -258.15932684125505, - "y": 656.5109602097457 - }, - "type": "stickyNote", - "data": { - "id": "stickyNote_0", - "label": "Sticky Note", - "version": 2, - "name": "stickyNote", - "type": "StickyNote", - "baseClasses": ["StickyNote"], - "tags": ["Utilities"], - "category": "Utilities", - "description": "Add a sticky note", - "inputParams": [ - { - "label": "", - "name": "note", - "type": "string", - "rows": 1, - "placeholder": "Type something here", - "optional": true, - "id": "stickyNote_0-input-note-string" - } - ], - "inputAnchors": [], - "inputs": { - "note": "In the Format Prompt Values, we can specify the variables used in prompt.\n\n{\n input_language: \"English\",\n output_language: \"French\"\n}\n\nIf the last variable is not specified, in this case {text}, user question will be used as value." - }, - "outputAnchors": [ - { - "id": "stickyNote_0-output-stickyNote-StickyNote", - "name": "stickyNote", - "label": "StickyNote", - "description": "Add a sticky note", - "type": "StickyNote" - } - ], - "outputs": {}, - "selected": false - }, - "width": 300, - "height": 243, - "selected": false, - "positionAbsolute": { - "x": -258.15932684125505, - "y": 656.5109602097457 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "chatOpenAI_0", - "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-model-BaseLanguageModel", - "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel-llmChain_0-llmChain_0-input-model-BaseLanguageModel", - "data": { - "label": "" - } - }, - { - "source": "chatPromptTemplate_0", - "sourceHandle": "chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate", - "target": "llmChain_0", - "targetHandle": "llmChain_0-input-prompt-BasePromptTemplate", - "type": "buttonedge", - "id": "chatPromptTemplate_0-chatPromptTemplate_0-output-chatPromptTemplate-ChatPromptTemplate|BaseChatPromptTemplate|BasePromptTemplate-llmChain_0-llmChain_0-input-prompt-BasePromptTemplate", - "data": { - "label": "" - } - } - ] -} diff --git a/packages/server/marketplaces/chatflows/Vectara RAG Chain.json b/packages/server/marketplaces/chatflows/Vectara RAG Chain.json deleted file mode 100644 index e2dcde49..00000000 --- a/packages/server/marketplaces/chatflows/Vectara RAG Chain.json +++ /dev/null @@ -1,398 +0,0 @@ -{ - "description": "Using Vectara for Retrieval Augmented Generation (RAG) to answer questions from documents", - "usecases": ["Documents QnA"], - "framework": ["Langchain"], - "nodes": [ - { - "width": 300, - "height": 520, - "id": "vectaraQAChain_0", - "position": { - "x": 740.28434119739, - "y": 164.93261446841598 - }, - "type": "customNode", - "data": { - "id": "vectaraQAChain_0", - "label": "Vectara QA Chain", - "version": 2, - "name": "vectaraQAChain", - "type": "VectaraQAChain", - "baseClasses": ["VectaraQAChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "QA chain for Vectara", - "inputParams": [ - { - "label": "Summarizer Prompt Name", - "name": "summarizerPromptName", - "description": "Summarize the results fetched from Vectara. Read more", - "type": "options", - "options": [ - { - "label": "vectara-summary-ext-v1.2.0 (gpt-3.5-turbo)", - "name": "vectara-summary-ext-v1.2.0" - }, - { - "label": "vectara-experimental-summary-ext-2023-10-23-small (gpt-3.5-turbo)", - "name": "vectara-experimental-summary-ext-2023-10-23-small", - "description": "In beta, available to both Growth and Scale Vectara users" - }, - { - "label": "vectara-summary-ext-v1.3.0 (gpt-4.0)", - "name": "vectara-summary-ext-v1.3.0", - "description": "Only available to paying Scale Vectara users" - }, - { - "label": "vectara-experimental-summary-ext-2023-10-23-med (gpt-4.0)", - "name": "vectara-experimental-summary-ext-2023-10-23-med", - "description": "In beta, only available to paying Scale Vectara users" - } - ], - "default": "vectara-summary-ext-v1.2.0", - "id": "vectaraQAChain_0-input-summarizerPromptName-options" - }, - { - "label": "Response Language", - "name": "responseLang", - "description": "Return the response in specific language. If not selected, Vectara will automatically detects the language. Read more", - "type": "options", - "options": [ - { - "label": "English", - "name": "eng" - }, - { - "label": "German", - "name": "deu" - }, - { - "label": "French", - "name": "fra" - }, - { - "label": "Chinese", - "name": "zho" - }, - { - "label": "Korean", - "name": "kor" - }, - { - "label": "Arabic", - "name": "ara" - }, - { - "label": "Russian", - "name": "rus" - }, - { - "label": "Thai", - "name": "tha" - }, - { - "label": "Dutch", - "name": "nld" - }, - { - "label": "Italian", - "name": "ita" - }, - { - "label": "Portuguese", - "name": "por" - }, - { - "label": "Spanish", - "name": "spa" - }, - { - "label": "Japanese", - "name": "jpn" - }, - { - "label": "Polish", - "name": "pol" - }, - { - "label": "Turkish", - "name": "tur" - }, - { - "label": "Vietnamese", - "name": "vie" - }, - { - "label": "Indonesian", - "name": "ind" - }, - { - "label": "Czech", - "name": "ces" - }, - { - "label": "Ukrainian", - "name": "ukr" - }, - { - "label": "Greek", - "name": "ell" - }, - { - "label": "Hebrew", - "name": "heb" - }, - { - "label": "Farsi/Persian", - "name": "fas" - }, - { - "label": "Hindi", - "name": "hin" - }, - { - "label": "Urdu", - "name": "urd" - }, - { - "label": "Swedish", - "name": "swe" - }, - { - "label": "Bengali", - "name": "ben" - }, - { - "label": "Malay", - "name": "msa" - }, - { - "label": "Romanian", - "name": "ron" - } - ], - "optional": true, - "default": "eng", - "id": "vectaraQAChain_0-input-responseLang-options" - }, - { - "label": "Max Summarized Results", - "name": "maxSummarizedResults", - "description": "Maximum results used to build the summarized response", - "type": "number", - "default": 7, - "id": "vectaraQAChain_0-input-maxSummarizedResults-number" - } - ], - "inputAnchors": [ - { - "label": "Vectara Store", - "name": "vectaraStore", - "type": "VectorStore", - "id": "vectaraQAChain_0-input-vectaraStore-VectorStore" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "vectaraQAChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "inputModeration": "", - "vectaraStore": "{{vectara_1.data.instance}}", - "summarizerPromptName": "vectara-experimental-summary-ext-2023-10-23-small", - "responseLang": "eng", - "maxSummarizedResults": 7 - }, - "outputAnchors": [ - { - "id": "vectaraQAChain_0-output-vectaraQAChain-VectaraQAChain|BaseChain|Runnable", - "name": "vectaraQAChain", - "label": "VectaraQAChain", - "type": "VectaraQAChain | BaseChain | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 740.28434119739, - "y": 164.93261446841598 - }, - "dragging": false - }, - { - "width": 300, - "height": 536, - "id": "vectara_1", - "position": { - "x": 139.43135627266395, - "y": 189.3685569634871 - }, - "type": "customNode", - "data": { - "id": "vectara_1", - "label": "Vectara", - "version": 2, - "name": "vectara", - "type": "Vectara", - "baseClasses": ["Vectara", "VectorStoreRetriever", "BaseRetriever"], - "category": "Vector Stores", - "description": "Upsert embedded data and perform similarity search upon query using Vectara, a LLM-powered search-as-a-service", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["vectaraApi"], - "id": "vectara_1-input-credential-credential" - }, - { - "label": "File", - "name": "file", - "description": "File to upload to Vectara. Supported file types: https://docs.vectara.com/docs/api-reference/indexing-apis/file-upload/file-upload-filetypes", - "type": "file", - "optional": true, - "id": "vectara_1-input-file-file" - }, - { - "label": "Metadata Filter", - "name": "filter", - "description": "Filter to apply to Vectara metadata. Refer to the documentation on how to use Vectara filters with Flowise.", - "type": "string", - "additionalParams": true, - "optional": true, - "id": "vectara_1-input-filter-string" - }, - { - "label": "Sentences Before", - "name": "sentencesBefore", - "description": "Number of sentences to fetch before the matched sentence. Defaults to 2.", - "type": "number", - "default": 2, - "additionalParams": true, - "optional": true, - "id": "vectara_1-input-sentencesBefore-number" - }, - { - "label": "Sentences After", - "name": "sentencesAfter", - "description": "Number of sentences to fetch after the matched sentence. Defaults to 2.", - "type": "number", - "default": 2, - "additionalParams": true, - "optional": true, - "id": "vectara_1-input-sentencesAfter-number" - }, - { - "label": "Lambda", - "name": "lambda", - "description": "Enable hybrid search to improve retrieval accuracy by adjusting the balance (from 0 to 1) between neural search and keyword-based search factors.A value of 0.0 means that only neural search is used, while a value of 1.0 means that only keyword-based search is used. Defaults to 0.0 (neural only).", - "default": 0, - "type": "number", - "additionalParams": true, - "optional": true, - "id": "vectara_1-input-lambda-number" - }, - { - "label": "Top K", - "name": "topK", - "description": "Number of top results to fetch. Defaults to 5", - "placeholder": "5", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "vectara_1-input-topK-number" - }, - { - "label": "MMR K", - "name": "mmrK", - "description": "Number of top results to fetch for MMR. Defaults to 50", - "placeholder": "50", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "vectara_1-input-mmrK-number" - }, - { - "label": "MMR diversity bias", - "name": "mmrDiversityBias", - "step": 0.1, - "description": "The diversity bias to use for MMR. This is a value between 0.0 and 1.0Values closer to 1.0 optimize for the most diverse results.Defaults to 0 (MMR disabled)", - "placeholder": "0.0", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "vectara_1-input-mmrDiversityBias-number" - } - ], - "inputAnchors": [ - { - "label": "Document", - "name": "document", - "type": "Document", - "list": true, - "optional": true, - "id": "vectara_1-input-document-Document" - } - ], - "inputs": { - "document": "", - "filter": "", - "sentencesBefore": 2, - "sentencesAfter": 2, - "lambda": "", - "topK": "", - "mmrK": "", - "mmrDiversityBias": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "vectara_1-output-retriever-Vectara|VectorStoreRetriever|BaseRetriever", - "name": "retriever", - "label": "Vectara Retriever", - "type": "Vectara | VectorStoreRetriever | BaseRetriever" - }, - { - "id": "vectara_1-output-vectorStore-Vectara|VectorStore", - "name": "vectorStore", - "label": "Vectara Vector Store", - "type": "Vectara | VectorStore" - } - ], - "default": "retriever" - } - ], - "outputs": { - "output": "vectorStore" - }, - "selected": false - }, - "positionAbsolute": { - "x": 139.43135627266395, - "y": 189.3685569634871 - }, - "selected": false, - "dragging": false - } - ], - "edges": [ - { - "source": "vectara_1", - "sourceHandle": "vectara_1-output-vectorStore-Vectara|VectorStore", - "target": "vectaraQAChain_0", - "targetHandle": "vectaraQAChain_0-input-vectaraStore-VectorStore", - "type": "buttonedge", - "id": "vectara_1-vectara_1-output-vectorStore-Vectara|VectorStore-vectaraQAChain_0-vectaraQAChain_0-input-vectaraStore-VectorStore" - } - ] -} diff --git a/packages/server/marketplaces/chatflows/WebPage QnA.json b/packages/server/marketplaces/chatflows/WebPage QnA.json deleted file mode 100644 index 14900ce6..00000000 --- a/packages/server/marketplaces/chatflows/WebPage QnA.json +++ /dev/null @@ -1,788 +0,0 @@ -{ - "description": "Scrape web pages to be used with Retrieval Augmented Generation (RAG) for question answering", - "usecases": ["Documents QnA"], - "framework": ["Langchain"], - "badge": "POPULAR", - "nodes": [ - { - "width": 300, - "height": 424, - "id": "openAIEmbeddings_0", - "position": { - "x": 805.4033852865127, - "y": 289.17383087232275 - }, - "type": "customNode", - "data": { - "id": "openAIEmbeddings_0", - "label": "OpenAI Embeddings", - "version": 4, - "name": "openAIEmbeddings", - "type": "OpenAIEmbeddings", - "baseClasses": ["OpenAIEmbeddings", "Embeddings"], - "category": "Embeddings", - "description": "OpenAI API to generate embeddings for a given text", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "openAIEmbeddings_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "text-embedding-ada-002", - "id": "openAIEmbeddings_0-input-modelName-asyncOptions" - }, - { - "label": "Strip New Lines", - "name": "stripNewLines", - "type": "boolean", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-stripNewLines-boolean" - }, - { - "label": "Batch Size", - "name": "batchSize", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-batchSize-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-basepath-string" - }, - { - "label": "Dimensions", - "name": "dimensions", - "type": "number", - "optional": true, - "additionalParams": true, - "id": "openAIEmbeddings_0-input-dimensions-number" - } - ], - "inputAnchors": [], - "inputs": { - "modelName": "text-embedding-ada-002", - "stripNewLines": "", - "batchSize": "", - "timeout": "", - "basepath": "", - "dimensions": "" - }, - "outputAnchors": [ - { - "id": "openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "name": "openAIEmbeddings", - "label": "OpenAIEmbeddings", - "description": "OpenAI API to generate embeddings for a given text", - "type": "OpenAIEmbeddings | Embeddings" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 805.4033852865127, - "y": 289.17383087232275 - }, - "dragging": false - }, - { - "width": 300, - "height": 378, - "id": "htmlToMarkdownTextSplitter_0", - "position": { - "x": 459.0189921792261, - "y": -21.97787557438943 - }, - "type": "customNode", - "data": { - "id": "htmlToMarkdownTextSplitter_0", - "label": "HtmlToMarkdown Text Splitter", - "version": 1, - "name": "htmlToMarkdownTextSplitter", - "type": "HtmlToMarkdownTextSplitter", - "baseClasses": [ - "HtmlToMarkdownTextSplitter", - "MarkdownTextSplitter", - "RecursiveCharacterTextSplitter", - "TextSplitter", - "BaseDocumentTransformer" - ], - "category": "Text Splitters", - "description": "Converts Html to Markdown and then split your content into documents based on the Markdown headers", - "inputParams": [ - { - "label": "Chunk Size", - "name": "chunkSize", - "type": "number", - "default": 1000, - "optional": true, - "id": "htmlToMarkdownTextSplitter_0-input-chunkSize-number" - }, - { - "label": "Chunk Overlap", - "name": "chunkOverlap", - "type": "number", - "optional": true, - "id": "htmlToMarkdownTextSplitter_0-input-chunkOverlap-number" - } - ], - "inputAnchors": [], - "inputs": { - "chunkSize": "4000", - "chunkOverlap": "" - }, - "outputAnchors": [ - { - "id": "htmlToMarkdownTextSplitter_0-output-htmlToMarkdownTextSplitter-HtmlToMarkdownTextSplitter|MarkdownTextSplitter|RecursiveCharacterTextSplitter|TextSplitter|BaseDocumentTransformer", - "name": "htmlToMarkdownTextSplitter", - "label": "HtmlToMarkdownTextSplitter", - "type": "HtmlToMarkdownTextSplitter | MarkdownTextSplitter | RecursiveCharacterTextSplitter | TextSplitter | BaseDocumentTransformer" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 459.0189921792261, - "y": -21.97787557438943 - }, - "dragging": false - }, - { - "width": 300, - "height": 532, - "id": "conversationalRetrievalQAChain_0", - "position": { - "x": 1892.82894546983, - "y": 282.2572649522094 - }, - "type": "customNode", - "data": { - "id": "conversationalRetrievalQAChain_0", - "label": "Conversational Retrieval QA Chain", - "version": 3, - "name": "conversationalRetrievalQAChain", - "type": "ConversationalRetrievalQAChain", - "baseClasses": ["ConversationalRetrievalQAChain", "BaseChain", "Runnable"], - "category": "Chains", - "description": "Document QA - built on RetrievalQAChain to provide a chat history component", - "inputParams": [ - { - "label": "Return Source Documents", - "name": "returnSourceDocuments", - "type": "boolean", - "optional": true, - "id": "conversationalRetrievalQAChain_0-input-returnSourceDocuments-boolean" - }, - { - "label": "Rephrase Prompt", - "name": "rephrasePrompt", - "type": "string", - "description": "Using previous chat history, rephrase question into a standalone question", - "warning": "Prompt must include input variables: {chat_history} and {question}", - "rows": 4, - "additionalParams": true, - "optional": true, - "default": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.\n\nChat History:\n{chat_history}\nFollow Up Input: {question}\nStandalone Question:", - "id": "conversationalRetrievalQAChain_0-input-rephrasePrompt-string" - }, - { - "label": "Response Prompt", - "name": "responsePrompt", - "type": "string", - "description": "Taking the rephrased question, search for answer from the provided context", - "warning": "Prompt must include input variable: {context}", - "rows": 4, - "additionalParams": true, - "optional": true, - "default": "You are a helpful assistant. Using the provided context, answer the user's question to the best of your ability using the resources provided.\nIf there is nothing in the context relevant to the question at hand, just say \"Hmm, I'm not sure.\" Don't try to make up an answer.\n------------\n{context}\n------------\nREMEMBER: If there is no relevant information within the context, just say \"Hmm, I'm not sure.\" Don't try to make up an answer.", - "id": "conversationalRetrievalQAChain_0-input-responsePrompt-string" - } - ], - "inputAnchors": [ - { - "label": "Chat Model", - "name": "model", - "type": "BaseChatModel", - "id": "conversationalRetrievalQAChain_0-input-model-BaseChatModel" - }, - { - "label": "Vector Store Retriever", - "name": "vectorStoreRetriever", - "type": "BaseRetriever", - "id": "conversationalRetrievalQAChain_0-input-vectorStoreRetriever-BaseRetriever" - }, - { - "label": "Memory", - "name": "memory", - "type": "BaseMemory", - "optional": true, - "description": "If left empty, a default BufferMemory will be used", - "id": "conversationalRetrievalQAChain_0-input-memory-BaseMemory" - }, - { - "label": "Input Moderation", - "description": "Detect text that could generate harmful output and prevent it from being sent to the language model", - "name": "inputModeration", - "type": "Moderation", - "optional": true, - "list": true, - "id": "conversationalRetrievalQAChain_0-input-inputModeration-Moderation" - } - ], - "inputs": { - "inputModeration": "", - "model": "{{chatOpenAI_0.data.instance}}", - "vectorStoreRetriever": "{{pinecone_0.data.instance}}", - "memory": "", - "returnSourceDocuments": true, - "rephrasePrompt": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.\n\nChat History:\n{chat_history}\nFollow Up Input: {question}\nStandalone Question:", - "responsePrompt": "You are a helpful assistant. Using the provided context, answer the user's question to the best of your ability using the resources provided.\nIf there is nothing in the context relevant to the question at hand, just say \"Hmm, I'm not sure.\" Don't try to make up an answer.\n------------\n{context}\n------------\nREMEMBER: If there is no relevant information within the context, just say \"Hmm, I'm not sure.\" Don't try to make up an answer." - }, - "outputAnchors": [ - { - "id": "conversationalRetrievalQAChain_0-output-conversationalRetrievalQAChain-ConversationalRetrievalQAChain|BaseChain|Runnable", - "name": "conversationalRetrievalQAChain", - "label": "ConversationalRetrievalQAChain", - "type": "ConversationalRetrievalQAChain | BaseChain | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1892.82894546983, - "y": 282.2572649522094 - }, - "dragging": false - }, - { - "width": 300, - "height": 426, - "id": "cheerioWebScraper_0", - "position": { - "x": 815.9295655148293, - "y": -190.50425962124604 - }, - "type": "customNode", - "data": { - "id": "cheerioWebScraper_0", - "label": "Cheerio Web Scraper", - "version": 1.1, - "name": "cheerioWebScraper", - "type": "Document", - "baseClasses": ["Document"], - "category": "Document Loaders", - "description": "Load data from webpages", - "inputParams": [ - { - "label": "URL", - "name": "url", - "type": "string", - "id": "cheerioWebScraper_0-input-url-string" - }, - { - "label": "Get Relative Links Method", - "name": "relativeLinksMethod", - "type": "options", - "description": "Select a method to retrieve relative links", - "options": [ - { - "label": "Web Crawl", - "name": "webCrawl", - "description": "Crawl relative links from HTML URL" - }, - { - "label": "Scrape XML Sitemap", - "name": "scrapeXMLSitemap", - "description": "Scrape relative links from XML sitemap URL" - } - ], - "optional": true, - "additionalParams": true, - "id": "cheerioWebScraper_0-input-relativeLinksMethod-options" - }, - { - "label": "Get Relative Links Limit", - "name": "limit", - "type": "number", - "optional": true, - "additionalParams": true, - "description": "Only used when \"Get Relative Links Method\" is selected. Set 0 to retrieve all relative links, default limit is 10.", - "warning": "Retrieving all links might take long time, and all links will be upserted again if the flow's state changed (eg: different URL, chunk size, etc)", - "id": "cheerioWebScraper_0-input-limit-number" - }, - { - "label": "Selector (CSS)", - "name": "selector", - "type": "string", - "description": "Specify a CSS selector to select the content to be extracted", - "optional": true, - "additionalParams": true, - "id": "cheerioWebScraper_0-input-selector-string" - }, - { - "label": "Metadata", - "name": "metadata", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "cheerioWebScraper_0-input-metadata-json" - } - ], - "inputAnchors": [ - { - "label": "Text Splitter", - "name": "textSplitter", - "type": "TextSplitter", - "optional": true, - "id": "cheerioWebScraper_0-input-textSplitter-TextSplitter" - } - ], - "inputs": { - "url": "https://flowiseai.com/", - "textSplitter": "{{htmlToMarkdownTextSplitter_0.data.instance}}", - "relativeLinksMethod": "", - "limit": "", - "metadata": "" - }, - "outputAnchors": [ - { - "id": "cheerioWebScraper_0-output-cheerioWebScraper-Document", - "name": "cheerioWebScraper", - "label": "Document", - "type": "Document" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 815.9295655148293, - "y": -190.50425962124604 - }, - "dragging": false - }, - { - "width": 300, - "height": 670, - "id": "chatOpenAI_0", - "position": { - "x": 1532.4907022314349, - "y": -270.38662863532466 - }, - "type": "customNode", - "data": { - "id": "chatOpenAI_0", - "label": "ChatOpenAI", - "version": 6, - "name": "chatOpenAI", - "type": "ChatOpenAI", - "baseClasses": ["ChatOpenAI", "BaseChatModel", "BaseLanguageModel", "Runnable"], - "category": "Chat Models", - "description": "Wrapper around OpenAI large language models that use the Chat endpoint", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["openAIApi"], - "id": "chatOpenAI_0-input-credential-credential" - }, - { - "label": "Model Name", - "name": "modelName", - "type": "asyncOptions", - "loadMethod": "listModels", - "default": "gpt-3.5-turbo", - "id": "chatOpenAI_0-input-modelName-options" - }, - { - "label": "Temperature", - "name": "temperature", - "type": "number", - "step": 0.1, - "default": 0.9, - "optional": true, - "id": "chatOpenAI_0-input-temperature-number" - }, - { - "label": "Max Tokens", - "name": "maxTokens", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-maxTokens-number" - }, - { - "label": "Top Probability", - "name": "topP", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-topP-number" - }, - { - "label": "Frequency Penalty", - "name": "frequencyPenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-frequencyPenalty-number" - }, - { - "label": "Presence Penalty", - "name": "presencePenalty", - "type": "number", - "step": 0.1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-presencePenalty-number" - }, - { - "label": "Timeout", - "name": "timeout", - "type": "number", - "step": 1, - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-timeout-number" - }, - { - "label": "BasePath", - "name": "basepath", - "type": "string", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-basepath-string" - }, - { - "label": "BaseOptions", - "name": "baseOptions", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "chatOpenAI_0-input-baseOptions-json" - }, - { - "label": "Allow Image Uploads", - "name": "allowImageUploads", - "type": "boolean", - "description": "Automatically uses gpt-4-vision-preview when image is being uploaded from chat. Only works with LLMChain, Conversation Chain, ReAct Agent, and Conversational Agent", - "default": false, - "optional": true, - "id": "chatOpenAI_0-input-allowImageUploads-boolean" - }, - { - "label": "Image Resolution", - "description": "This parameter controls the resolution in which the model views the image.", - "name": "imageResolution", - "type": "options", - "options": [ - { - "label": "Low", - "name": "low" - }, - { - "label": "High", - "name": "high" - }, - { - "label": "Auto", - "name": "auto" - } - ], - "default": "low", - "optional": false, - "additionalParams": true, - "id": "chatOpenAI_0-input-imageResolution-options" - } - ], - "inputAnchors": [ - { - "label": "Cache", - "name": "cache", - "type": "BaseCache", - "optional": true, - "id": "chatOpenAI_0-input-cache-BaseCache" - } - ], - "inputs": { - "cache": "", - "modelName": "gpt-3.5-turbo", - "temperature": 0.9, - "maxTokens": "", - "topP": "", - "frequencyPenalty": "", - "presencePenalty": "", - "timeout": "", - "basepath": "", - "baseOptions": "", - "allowImageUploads": true, - "imageResolution": "low" - }, - "outputAnchors": [ - { - "id": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "name": "chatOpenAI", - "label": "ChatOpenAI", - "type": "ChatOpenAI | BaseChatModel | BaseLanguageModel | Runnable" - } - ], - "outputs": {}, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1532.4907022314349, - "y": -270.38662863532466 - }, - "dragging": false - }, - { - "width": 300, - "height": 555, - "id": "pinecone_0", - "position": { - "x": 1182.9660159923678, - "y": 56.45789225898284 - }, - "type": "customNode", - "data": { - "id": "pinecone_0", - "label": "Pinecone", - "version": 3, - "name": "pinecone", - "type": "Pinecone", - "baseClasses": ["Pinecone", "VectorStoreRetriever", "BaseRetriever"], - "category": "Vector Stores", - "description": "Upsert embedded data and perform similarity or mmr search using Pinecone, a leading fully managed hosted vector database", - "inputParams": [ - { - "label": "Connect Credential", - "name": "credential", - "type": "credential", - "credentialNames": ["pineconeApi"], - "id": "pinecone_0-input-credential-credential" - }, - { - "label": "Pinecone Index", - "name": "pineconeIndex", - "type": "string", - "id": "pinecone_0-input-pineconeIndex-string" - }, - { - "label": "Pinecone Namespace", - "name": "pineconeNamespace", - "type": "string", - "placeholder": "my-first-namespace", - "additionalParams": true, - "optional": true, - "id": "pinecone_0-input-pineconeNamespace-string" - }, - { - "label": "Pinecone Metadata Filter", - "name": "pineconeMetadataFilter", - "type": "json", - "optional": true, - "additionalParams": true, - "id": "pinecone_0-input-pineconeMetadataFilter-json" - }, - { - "label": "Top K", - "name": "topK", - "description": "Number of top results to fetch. Default to 4", - "placeholder": "4", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "pinecone_0-input-topK-number" - }, - { - "label": "Search Type", - "name": "searchType", - "type": "options", - "default": "similarity", - "options": [ - { - "label": "Similarity", - "name": "similarity" - }, - { - "label": "Max Marginal Relevance", - "name": "mmr" - } - ], - "additionalParams": true, - "optional": true, - "id": "pinecone_0-input-searchType-options" - }, - { - "label": "Fetch K (for MMR Search)", - "name": "fetchK", - "description": "Number of initial documents to fetch for MMR reranking. Default to 20. Used only when the search type is MMR", - "placeholder": "20", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "pinecone_0-input-fetchK-number" - }, - { - "label": "Lambda (for MMR Search)", - "name": "lambda", - "description": "Number between 0 and 1 that determines the degree of diversity among the results, where 0 corresponds to maximum diversity and 1 to minimum diversity. Used only when the search type is MMR", - "placeholder": "0.5", - "type": "number", - "additionalParams": true, - "optional": true, - "id": "pinecone_0-input-lambda-number" - } - ], - "inputAnchors": [ - { - "label": "Document", - "name": "document", - "type": "Document", - "list": true, - "optional": true, - "id": "pinecone_0-input-document-Document" - }, - { - "label": "Embeddings", - "name": "embeddings", - "type": "Embeddings", - "id": "pinecone_0-input-embeddings-Embeddings" - } - ], - "inputs": { - "document": ["{{cheerioWebScraper_0.data.instance}}"], - "embeddings": "{{openAIEmbeddings_0.data.instance}}", - "pineconeIndex": "", - "pineconeNamespace": "", - "pineconeMetadataFilter": "", - "topK": "", - "searchType": "similarity", - "fetchK": "", - "lambda": "" - }, - "outputAnchors": [ - { - "name": "output", - "label": "Output", - "type": "options", - "options": [ - { - "id": "pinecone_0-output-retriever-Pinecone|VectorStoreRetriever|BaseRetriever", - "name": "retriever", - "label": "Pinecone Retriever", - "type": "Pinecone | VectorStoreRetriever | BaseRetriever" - }, - { - "id": "pinecone_0-output-vectorStore-Pinecone|VectorStore", - "name": "vectorStore", - "label": "Pinecone Vector Store", - "type": "Pinecone | VectorStore" - } - ], - "default": "retriever" - } - ], - "outputs": { - "output": "retriever" - }, - "selected": false - }, - "selected": false, - "positionAbsolute": { - "x": 1182.9660159923678, - "y": 56.45789225898284 - }, - "dragging": false - } - ], - "edges": [ - { - "source": "htmlToMarkdownTextSplitter_0", - "sourceHandle": "htmlToMarkdownTextSplitter_0-output-htmlToMarkdownTextSplitter-HtmlToMarkdownTextSplitter|MarkdownTextSplitter|RecursiveCharacterTextSplitter|TextSplitter|BaseDocumentTransformer", - "target": "cheerioWebScraper_0", - "targetHandle": "cheerioWebScraper_0-input-textSplitter-TextSplitter", - "type": "buttonedge", - "id": "htmlToMarkdownTextSplitter_0-htmlToMarkdownTextSplitter_0-output-htmlToMarkdownTextSplitter-HtmlToMarkdownTextSplitter|MarkdownTextSplitter|RecursiveCharacterTextSplitter|TextSplitter|BaseDocumentTransformer-cheerioWebScraper_0-cheerioWebScraper_0-input-textSplitter-TextSplitter", - "data": { - "label": "" - } - }, - { - "source": "chatOpenAI_0", - "sourceHandle": "chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable", - "target": "conversationalRetrievalQAChain_0", - "targetHandle": "conversationalRetrievalQAChain_0-input-model-BaseChatModel", - "type": "buttonedge", - "id": "chatOpenAI_0-chatOpenAI_0-output-chatOpenAI-ChatOpenAI|BaseChatModel|BaseLanguageModel|Runnable-conversationalRetrievalQAChain_0-conversationalRetrievalQAChain_0-input-model-BaseChatModel", - "data": { - "label": "" - } - }, - { - "source": "cheerioWebScraper_0", - "sourceHandle": "cheerioWebScraper_0-output-cheerioWebScraper-Document", - "target": "pinecone_0", - "targetHandle": "pinecone_0-input-document-Document", - "type": "buttonedge", - "id": "cheerioWebScraper_0-cheerioWebScraper_0-output-cheerioWebScraper-Document-pinecone_0-pinecone_0-input-document-Document", - "data": { - "label": "" - } - }, - { - "source": "openAIEmbeddings_0", - "sourceHandle": "openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings", - "target": "pinecone_0", - "targetHandle": "pinecone_0-input-embeddings-Embeddings", - "type": "buttonedge", - "id": "openAIEmbeddings_0-openAIEmbeddings_0-output-openAIEmbeddings-OpenAIEmbeddings|Embeddings-pinecone_0-pinecone_0-input-embeddings-Embeddings", - "data": { - "label": "" - } - }, - { - "source": "pinecone_0", - "sourceHandle": "pinecone_0-output-retriever-Pinecone|VectorStoreRetriever|BaseRetriever", - "target": "conversationalRetrievalQAChain_0", - "targetHandle": "conversationalRetrievalQAChain_0-input-vectorStoreRetriever-BaseRetriever", - "type": "buttonedge", - "id": "pinecone_0-pinecone_0-output-retriever-Pinecone|VectorStoreRetriever|BaseRetriever-conversationalRetrievalQAChain_0-conversationalRetrievalQAChain_0-input-vectorStoreRetriever-BaseRetriever", - "data": { - "label": "" - } - } - ] -} diff --git a/packages/server/src/services/agentflowv2-generator/index.ts b/packages/server/src/services/agentflowv2-generator/index.ts index 4d987b90..c41a2018 100644 --- a/packages/server/src/services/agentflowv2-generator/index.ts +++ b/packages/server/src/services/agentflowv2-generator/index.ts @@ -116,8 +116,9 @@ const getAllAgentflowv2Marketplaces = async () => { } }) + const title = file.split('.json')[0] const template = { - title: file.split('.json')[0], + title, description: fileDataObj.description || `Template from ${file}`, usecases: fileDataObj.usecases || [], nodes: filteredNodes, @@ -126,7 +127,11 @@ const getAllAgentflowv2Marketplaces = async () => { // Validate template against schema const validatedTemplate = AgentFlowV2Type.parse(template) - templates.push(validatedTemplate) + templates.push({ + ...validatedTemplate, + // @ts-ignore + title: title + }) } catch (error) { console.error(`Error processing template file ${file}:`, error) // Continue with next file instead of failing completely diff --git a/packages/server/src/services/documentstore/index.ts b/packages/server/src/services/documentstore/index.ts index e9e203d2..355bc551 100644 --- a/packages/server/src/services/documentstore/index.ts +++ b/packages/server/src/services/documentstore/index.ts @@ -1613,8 +1613,12 @@ const upsertDocStore = async ( throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, `Error: Invalid metadata`) } } - const replaceExisting = data.replaceExisting ?? false - const createNewDocStore = data.createNewDocStore ?? false + const replaceExisting = + typeof data.replaceExisting === 'string' ? (data.replaceExisting as string).toLowerCase() === 'true' : data.replaceExisting ?? false + const createNewDocStore = + typeof data.createNewDocStore === 'string' + ? (data.createNewDocStore as string).toLowerCase() === 'true' + : data.createNewDocStore ?? false const newLoader = typeof data.loader === 'string' ? JSON.parse(data.loader) : data.loader const newSplitter = typeof data.splitter === 'string' ? JSON.parse(data.splitter) : data.splitter const newVectorStore = typeof data.vectorStore === 'string' ? JSON.parse(data.vectorStore) : data.vectorStore diff --git a/packages/server/src/services/marketplaces/index.ts b/packages/server/src/services/marketplaces/index.ts index bea25d4f..6f7f9c6b 100644 --- a/packages/server/src/services/marketplaces/index.ts +++ b/packages/server/src/services/marketplaces/index.ts @@ -69,6 +69,8 @@ const getAllTemplates = async () => { templates.push(template) }) + /* + * Agentflow is deprecated marketplaceDir = path.join(__dirname, '..', '..', '..', 'marketplaces', 'agentflows') jsonsInDir = fs.readdirSync(marketplaceDir).filter((file) => path.extname(file) === '.json') jsonsInDir.forEach((file) => { @@ -87,7 +89,7 @@ const getAllTemplates = async () => { description: fileDataObj?.description || '' } templates.push(template) - }) + })*/ marketplaceDir = path.join(__dirname, '..', '..', '..', 'marketplaces', 'agentflowsv2') jsonsInDir = fs.readdirSync(marketplaceDir).filter((file) => path.extname(file) === '.json') @@ -108,11 +110,24 @@ const getAllTemplates = async () => { } templates.push(template) }) - const sortedTemplates = templates.sort((a, b) => a.templateName.localeCompare(b.templateName)) - const FlowiseDocsQnAIndex = sortedTemplates.findIndex((tmp) => tmp.templateName === 'Flowise Docs QnA') - if (FlowiseDocsQnAIndex > 0) { - sortedTemplates.unshift(sortedTemplates.splice(FlowiseDocsQnAIndex, 1)[0]) - } + const sortedTemplates = templates.sort((a, b) => { + // Prioritize AgentflowV2 templates first + if (a.type === 'AgentflowV2' && b.type !== 'AgentflowV2') { + return -1 + } + if (b.type === 'AgentflowV2' && a.type !== 'AgentflowV2') { + return 1 + } + // Put Tool templates last + if (a.type === 'Tool' && b.type !== 'Tool') { + return 1 + } + if (b.type === 'Tool' && a.type !== 'Tool') { + return -1 + } + // For same types, sort alphabetically by templateName + return a.templateName.localeCompare(b.templateName) + }) const dbResponse = sortedTemplates return dbResponse } catch (error) { diff --git a/packages/server/src/utils/buildAgentflow.ts b/packages/server/src/utils/buildAgentflow.ts index 40953bf3..591e85a5 100644 --- a/packages/server/src/utils/buildAgentflow.ts +++ b/packages/server/src/utils/buildAgentflow.ts @@ -40,7 +40,8 @@ import { getGlobalVariable, getStartingNode, getTelemetryFlowObj, - QUESTION_VAR_PREFIX + QUESTION_VAR_PREFIX, + CURRENT_DATE_TIME_VAR_PREFIX } from '.' import { ChatFlow } from '../database/entities/ChatFlow' import { Variable } from '../database/entities/Variable' @@ -294,9 +295,18 @@ export const resolveVariables = async ( resolvedValue = resolvedValue.replace(match, flowConfig?.runtimeChatHistoryLength ?? 0) } + if (variableFullPath === CURRENT_DATE_TIME_VAR_PREFIX) { + resolvedValue = resolvedValue.replace(match, new Date().toISOString()) + } + if (variableFullPath.startsWith('$iteration')) { if (iterationContext && iterationContext.value) { - if (typeof iterationContext.value === 'string') { + if (variableFullPath === '$iteration') { + // If it's exactly $iteration, stringify the entire value + const formattedValue = + typeof iterationContext.value === 'object' ? JSON.stringify(iterationContext.value) : iterationContext.value + resolvedValue = resolvedValue.replace(match, formattedValue) + } else if (typeof iterationContext.value === 'string') { resolvedValue = resolvedValue.replace(match, iterationContext?.value) } else if (typeof iterationContext.value === 'object') { const iterationValue = get(iterationContext.value, variableFullPath.replace('$iteration.', '')) @@ -342,8 +352,10 @@ export const resolveVariables = async ( const [, nodeIdPart, outputPath] = outputMatch // Clean nodeId (handle escaped underscores) const cleanNodeId = nodeIdPart.replace('\\', '') + // Find the last (most recent) matching node data instead of the first one const nodeData = [...agentFlowExecutedData].reverse().find((d) => d.nodeId === cleanNodeId) + if (nodeData?.data?.output && outputPath.trim()) { const variableValue = get(nodeData.data.output, outputPath) if (variableValue !== undefined) { @@ -1234,6 +1246,20 @@ const checkForMultipleStartNodes = (startingNodeIds: string[], isRecursive: bool } } +const parseFormStringToJson = (formString: string): Record => { + const result: Record = {} + const lines = formString.split('\n') + + for (const line of lines) { + const [key, value] = line.split(': ').map((part) => part.trim()) + if (key && value) { + result[key] = value + } + } + + return result +} + /* * Function to traverse the flow graph and execute the nodes */ @@ -1376,7 +1402,12 @@ export const executeAgentFlow = async ({ if (previousStartAgent) { const previousStartAgentOutput = previousStartAgent.data.output if (previousStartAgentOutput && typeof previousStartAgentOutput === 'object' && 'form' in previousStartAgentOutput) { - agentflowRuntime.form = previousStartAgentOutput.form + const formValues = previousStartAgentOutput.form + if (typeof formValues === 'string') { + agentflowRuntime.form = parseFormStringToJson(formValues) + } else { + agentflowRuntime.form = formValues + } } } } diff --git a/packages/server/src/utils/index.ts b/packages/server/src/utils/index.ts index 11003095..45abe5d0 100644 --- a/packages/server/src/utils/index.ts +++ b/packages/server/src/utils/index.ts @@ -71,6 +71,7 @@ export const QUESTION_VAR_PREFIX = 'question' export const FILE_ATTACHMENT_PREFIX = 'file_attachment' export const CHAT_HISTORY_VAR_PREFIX = 'chat_history' export const RUNTIME_MESSAGES_LENGTH_VAR_PREFIX = 'runtime_messages_length' +export const CURRENT_DATE_TIME_VAR_PREFIX = 'current_date_time' export const REDACTED_CREDENTIAL_VALUE = '_FLOWISE_BLANK_07167752-1a71-43b1-bf8f-4f32252165db' let secretsManagerClient: SecretsManagerClient | null = null diff --git a/packages/server/src/utils/logger.ts b/packages/server/src/utils/logger.ts index 43a75c92..3b5a0bd5 100644 --- a/packages/server/src/utils/logger.ts +++ b/packages/server/src/utils/logger.ts @@ -28,17 +28,21 @@ if (process.env.STORAGE_TYPE === 's3') { const customURL = process.env.S3_ENDPOINT_URL const forcePathStyle = process.env.S3_FORCE_PATH_STYLE === 'true' - if (!region || !s3Bucket) { + if (!region || region.trim() === '' || !s3Bucket || s3Bucket.trim() === '') { throw new Error('S3 storage configuration is missing') } const s3Config: S3ClientConfig = { region: region, - endpoint: customURL, forcePathStyle: forcePathStyle } - if (accessKeyId && secretAccessKey) { + // Only include endpoint if customURL is not empty + if (customURL && customURL.trim() !== '') { + s3Config.endpoint = customURL + } + + if (accessKeyId && accessKeyId.trim() !== '' && secretAccessKey && secretAccessKey.trim() !== '') { s3Config.credentials = { accessKeyId: accessKeyId, secretAccessKey: secretAccessKey diff --git a/packages/ui/src/ui-component/button/FlowListMenu.jsx b/packages/ui/src/ui-component/button/FlowListMenu.jsx index e70bbd85..d3c2e259 100644 --- a/packages/ui/src/ui-component/button/FlowListMenu.jsx +++ b/packages/ui/src/ui-component/button/FlowListMenu.jsx @@ -166,7 +166,7 @@ export default function FlowListMenu({ chatflow, isAgentCanvas, isAgentflowV2, s } try { await updateChatflowApi.request(chatflow.id, updateBody) - if (isAgentCanvas && localStorage.getItem('agentFlowVersion') === 'v2') { + if (isAgentCanvas && isAgentflowV2) { await updateFlowsApi.request('AGENTFLOW') } else { await updateFlowsApi.request(isAgentCanvas ? 'MULTIAGENT' : undefined) @@ -241,7 +241,7 @@ export default function FlowListMenu({ chatflow, isAgentCanvas, isAgentflowV2, s if (isConfirmed) { try { await chatflowsApi.deleteChatflow(chatflow.id) - if (isAgentCanvas && localStorage.getItem('agentFlowVersion') === 'v2') { + if (isAgentCanvas && isAgentflowV2) { await updateFlowsApi.request('AGENTFLOW') } else { await updateFlowsApi.request(isAgentCanvas ? 'MULTIAGENT' : undefined) diff --git a/packages/ui/src/ui-component/input/RichInput.jsx b/packages/ui/src/ui-component/input/RichInput.jsx index 50c7e7cf..7be62551 100644 --- a/packages/ui/src/ui-component/input/RichInput.jsx +++ b/packages/ui/src/ui-component/input/RichInput.jsx @@ -37,7 +37,7 @@ const extensions = (availableNodesForVariable, availableState, acceptNodeOutputA ] // Add styled component for editor wrapper -const StyledEditorContent = styled(EditorContent)(({ theme, rows }) => ({ +const StyledEditorContent = styled(EditorContent)(({ theme, rows, disabled }) => ({ '& .ProseMirror': { padding: '0px 14px', height: rows ? `${rows * 1.4375}rem` : '2.4rem', @@ -45,30 +45,26 @@ const StyledEditorContent = styled(EditorContent)(({ theme, rows }) => ({ overflowX: rows ? 'auto' : 'hidden', lineHeight: rows ? '1.4375em' : '0.875em', fontWeight: 500, - color: theme.palette.grey[900], + color: disabled ? theme.palette.action.disabled : theme.palette.grey[900], border: `1px solid ${theme.palette.grey[900] + 25}`, borderRadius: '10px', backgroundColor: theme.palette.textBackground.main, boxSizing: 'border-box', whiteSpace: rows ? 'pre-wrap' : 'nowrap', '&:hover': { - borderColor: theme.palette.text.primary, - cursor: 'text' + borderColor: disabled ? `${theme.palette.grey[900] + 25}` : theme.palette.text.primary, + cursor: disabled ? 'default' : 'text' }, '&:focus': { - borderColor: theme.palette.primary.main, + borderColor: disabled ? `${theme.palette.grey[900] + 25}` : theme.palette.primary.main, outline: 'none' }, - '&[disabled]': { - backgroundColor: theme.palette.action.disabledBackground, - color: theme.palette.action.disabled - }, // Placeholder for first paragraph when editor is empty '& p.is-editor-empty:first-of-type::before': { content: 'attr(data-placeholder)', float: 'left', - color: theme.palette.text.primary, - opacity: 0.4, + color: disabled ? theme.palette.action.disabled : theme.palette.text.primary, + opacity: disabled ? 0.6 : 0.4, pointerEvents: 'none', height: 0 } @@ -121,7 +117,7 @@ export const RichInput = ({ inputParam, value, nodes, edges, nodeId, onChange, d return ( - + ) } diff --git a/packages/ui/src/ui-component/input/suggestionOption.js b/packages/ui/src/ui-component/input/suggestionOption.js index 229870e2..587fa978 100644 --- a/packages/ui/src/ui-component/input/suggestionOption.js +++ b/packages/ui/src/ui-component/input/suggestionOption.js @@ -59,6 +59,12 @@ export const suggestionOptions = ( description: 'Past conversation history between user and AI', category: 'Chat Context' }, + { + id: 'current_date_time', + mentionLabel: 'current_date_time', + description: 'Current date and time', + category: 'Chat Context' + }, { id: 'runtime_messages_length', mentionLabel: 'runtime_messages_length', diff --git a/packages/ui/src/ui-component/markdown/Markdown.css b/packages/ui/src/ui-component/markdown/Markdown.css index c152a97e..ae93f1d1 100644 --- a/packages/ui/src/ui-component/markdown/Markdown.css +++ b/packages/ui/src/ui-component/markdown/Markdown.css @@ -19,3 +19,45 @@ border-width: 1px !important; padding: 10px !important; } + +.react-markdown h1, +.react-markdown h2, +.react-markdown h3, +.react-markdown h4, +.react-markdown h5, +.react-markdown h6 { + line-height: 1.4; + margin: 0.8em 0 0.4em 0; + font-weight: 600; +} + +.react-markdown h1 { + font-size: 1.8em; +} + +.react-markdown h2 { + font-size: 1.5em; +} + +.react-markdown h3 { + font-size: 1.3em; +} + +.react-markdown h4 { + font-size: 1.1em; +} + +.react-markdown h5 { + font-size: 1em; + font-weight: 700; +} + +.react-markdown h6 { + font-size: 0.9em; + font-weight: 700; +} + +.react-markdown p { + line-height: 1.6; + margin: 0.5em 0; +} diff --git a/packages/ui/src/ui-component/table/FlowListTable.jsx b/packages/ui/src/ui-component/table/FlowListTable.jsx index 43087d61..a61df9ed 100644 --- a/packages/ui/src/ui-component/table/FlowListTable.jsx +++ b/packages/ui/src/ui-component/table/FlowListTable.jsx @@ -87,7 +87,7 @@ export const FlowListTable = ({ if (!isAgentCanvas) { return `/canvas/${row.id}` } else { - return localStorage.getItem('agentFlowVersion') === 'v2' ? `/v2/agentcanvas/${row.id}` : `/agentcanvas/${row.id}` + return isAgentflowV2 ? `/v2/agentcanvas/${row.id}` : `/agentcanvas/${row.id}` } } diff --git a/packages/ui/src/ui-component/table/MarketplaceTable.jsx b/packages/ui/src/ui-component/table/MarketplaceTable.jsx index 52b1e68c..23a35c22 100644 --- a/packages/ui/src/ui-component/table/MarketplaceTable.jsx +++ b/packages/ui/src/ui-component/table/MarketplaceTable.jsx @@ -213,7 +213,13 @@ export const MarketplaceTable = ({ .split(';') .map((tag, index) => (