mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 19:00:59 +03:00
Feature/seq agents (#2798)
* update build functions * sequential agents * update langchain to 0.2, added sequential agent nodes * add marketplace templates * update howto wordings * Merge branch 'main' into feature/Seq-Agents # Conflicts: # pnpm-lock.yaml * update deprecated functions and add new sequential nodes * add marketplace templates * update marketplace templates, add structured output to llm node * add multi agents template * update llm node with bindmodels * update cypress version * update templates sticky note wordings * update tool node to include human in loop action * update structured outputs error from models * update cohere package to resolve google genai pipeThrough bug * update mistral package version, added message reconstruction before invoke seq agent * add HITL to agent * update state messages restructuring * update load and split methods for s3 directory
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import moment from 'moment'
|
||||
import { uniq } from 'lodash'
|
||||
|
||||
export const getUniqueNodeId = (nodeData, nodes) => {
|
||||
// Get amount of same nodes
|
||||
@@ -52,7 +53,9 @@ export const initNode = (nodeData, newNodeId) => {
|
||||
'code',
|
||||
'date',
|
||||
'file',
|
||||
'folder'
|
||||
'folder',
|
||||
'tabs',
|
||||
'conditionFunction' // This is a special type for condition functions
|
||||
]
|
||||
|
||||
// Inputs
|
||||
@@ -80,6 +83,7 @@ export const initNode = (nodeData, newNodeId) => {
|
||||
// Outputs
|
||||
const outputAnchors = []
|
||||
for (let i = 0; i < outgoing; i += 1) {
|
||||
if (nodeData.hideOutput) continue
|
||||
if (nodeData.outputs && nodeData.outputs.length) {
|
||||
const options = []
|
||||
for (let j = 0; j < nodeData.outputs.length; j += 1) {
|
||||
@@ -100,7 +104,9 @@ export const initNode = (nodeData, newNodeId) => {
|
||||
name: nodeData.outputs[j].name,
|
||||
label: nodeData.outputs[j].label,
|
||||
description: nodeData.outputs[j].description ?? '',
|
||||
type
|
||||
type,
|
||||
isAnchor: nodeData.outputs[j]?.isAnchor,
|
||||
hidden: nodeData.outputs[j]?.hidden
|
||||
}
|
||||
options.push(newOutputOption)
|
||||
}
|
||||
@@ -404,14 +410,43 @@ export const getAvailableNodesForVariable = (nodes, edges, target, targetHandle)
|
||||
// example edge id = "llmChain_0-llmChain_0-output-outputPrediction-string|json-llmChain_1-llmChain_1-input-promptValues-string"
|
||||
// {source} -{sourceHandle} -{target} -{targetHandle}
|
||||
const parentNodes = []
|
||||
const inputEdges = edges.filter((edg) => edg.target === target && edg.targetHandle === targetHandle)
|
||||
if (inputEdges && inputEdges.length) {
|
||||
for (let j = 0; j < inputEdges.length; j += 1) {
|
||||
const node = nodes.find((nd) => nd.id === inputEdges[j].source)
|
||||
parentNodes.push(node)
|
||||
}
|
||||
|
||||
const isSeqAgent = nodes.find((nd) => nd.id === target)?.data?.category === 'Sequential Agents'
|
||||
|
||||
function collectParentNodes(targetNodeId, nodes, edges) {
|
||||
const inputEdges = edges.filter(
|
||||
(edg) => edg.target === targetNodeId && edg.targetHandle.includes(`${targetNodeId}-input-sequentialNode`)
|
||||
)
|
||||
|
||||
// Traverse each edge found
|
||||
inputEdges.forEach((edge) => {
|
||||
const parentNode = nodes.find((nd) => nd.id === edge.source)
|
||||
if (!parentNode) return
|
||||
|
||||
// Recursive call to explore further up the tree
|
||||
collectParentNodes(parentNode.id, nodes, edges)
|
||||
|
||||
// Check and add the parent node to the list if it does not include specific names
|
||||
const excludeNodeNames = ['seqAgent', 'seqLLMNode', 'seqToolNode']
|
||||
if (excludeNodeNames.includes(parentNode.data.name)) {
|
||||
parentNodes.push(parentNode)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (isSeqAgent) {
|
||||
collectParentNodes(target, nodes, edges)
|
||||
return uniq(parentNodes)
|
||||
} else {
|
||||
const inputEdges = edges.filter((edg) => edg.target === target && edg.targetHandle === targetHandle)
|
||||
if (inputEdges && inputEdges.length) {
|
||||
for (let j = 0; j < inputEdges.length; j += 1) {
|
||||
const node = nodes.find((nd) => nd.id === inputEdges[j].source)
|
||||
parentNodes.push(node)
|
||||
}
|
||||
}
|
||||
return parentNodes
|
||||
}
|
||||
return parentNodes
|
||||
}
|
||||
|
||||
export const getUpsertDetails = (nodes, edges) => {
|
||||
@@ -783,3 +818,115 @@ export const kFormatter = (num) => {
|
||||
const item = lookup.findLast((item) => num >= item.value)
|
||||
return item ? (num / item.value).toFixed(1).replace(regexp, '').concat(item.symbol) : '0'
|
||||
}
|
||||
|
||||
const toCamelCase = (str) => {
|
||||
return str
|
||||
.split(' ') // Split by space to process each word
|
||||
.map((word, index) => (index === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()))
|
||||
.join('') // Join the words back into a single string
|
||||
}
|
||||
|
||||
const createJsonArray = (labels) => {
|
||||
return labels.map((label) => {
|
||||
return {
|
||||
label: label,
|
||||
name: toCamelCase(label),
|
||||
baseClasses: ['Agent', 'LLMNode', 'ToolNode'],
|
||||
isAnchor: true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const getCustomConditionOutputs = (value, nodeId, existingEdges, isDataGrid) => {
|
||||
// Regex to find return statements and capture returned values
|
||||
const regex = /return\s+(['"`])(.*?)\1/g
|
||||
let match
|
||||
const numberOfReturns = []
|
||||
|
||||
if (!isDataGrid) {
|
||||
// Loop over the matches of the regex
|
||||
while ((match = regex.exec(value)) !== null) {
|
||||
// Push the captured group, which is the actual return value, into results
|
||||
numberOfReturns.push(match[2])
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const parsedValue = JSON.parse(value)
|
||||
if (parsedValue && parsedValue.length) {
|
||||
for (const item of parsedValue) {
|
||||
if (!item.variable) {
|
||||
alert('Please specify a Variable. Try connecting Condition node to a previous node and select the variable')
|
||||
return undefined
|
||||
}
|
||||
if (!item.output) {
|
||||
alert('Please specify an Output Name')
|
||||
return undefined
|
||||
}
|
||||
if (!item.operation) {
|
||||
alert('Please select an operation for the condition')
|
||||
return undefined
|
||||
}
|
||||
numberOfReturns.push(item.output)
|
||||
}
|
||||
numberOfReturns.push('End')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error parsing JSON', e)
|
||||
}
|
||||
}
|
||||
|
||||
if (numberOfReturns.length === 0) {
|
||||
if (isDataGrid) alert('Please add an item for the condition')
|
||||
else
|
||||
alert(
|
||||
'Please add a return statement in the condition code to define the output. You can refer to How to Use for more information.'
|
||||
)
|
||||
return undefined
|
||||
}
|
||||
|
||||
const outputs = createJsonArray(numberOfReturns.sort())
|
||||
|
||||
const outputAnchors = []
|
||||
|
||||
const options = []
|
||||
for (let j = 0; j < outputs.length; j += 1) {
|
||||
let baseClasses = ''
|
||||
let type = ''
|
||||
|
||||
const outputBaseClasses = outputs[j].baseClasses ?? []
|
||||
if (outputBaseClasses.length > 1) {
|
||||
baseClasses = outputBaseClasses.join('|')
|
||||
type = outputBaseClasses.join(' | ')
|
||||
} else if (outputBaseClasses.length === 1) {
|
||||
baseClasses = outputBaseClasses[0]
|
||||
type = outputBaseClasses[0]
|
||||
}
|
||||
|
||||
const newOutputOption = {
|
||||
id: `${nodeId}-output-${outputs[j].name}-${baseClasses}`,
|
||||
name: outputs[j].name,
|
||||
label: outputs[j].label,
|
||||
type,
|
||||
isAnchor: outputs[j]?.isAnchor
|
||||
}
|
||||
options.push(newOutputOption)
|
||||
}
|
||||
const newOutput = {
|
||||
name: 'output',
|
||||
label: 'Output',
|
||||
type: 'options',
|
||||
options
|
||||
}
|
||||
outputAnchors.push(newOutput)
|
||||
|
||||
// Remove edges
|
||||
let newEdgeSourceHandles = []
|
||||
for (const anchor of options) {
|
||||
const anchorId = anchor.id
|
||||
newEdgeSourceHandles.push(anchorId)
|
||||
}
|
||||
|
||||
const toBeRemovedEdgeIds = existingEdges.filter((edge) => !newEdgeSourceHandles.includes(edge.sourceHandle)).map((edge) => edge.id)
|
||||
|
||||
return { outputAnchors, toBeRemovedEdgeIds }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user