2023-11-29 03:13:55 -08:00
import { NodeConnectionType , NodeOperationError } from 'n8n-workflow' ;
import type {
ConnectionTypes ,
INodeInputConfiguration ,
INodeInputFilter ,
IExecuteFunctions ,
INodeExecutionData ,
INodeType ,
INodeTypeDescription ,
2024-05-15 03:02:21 -07:00
INodeProperties ,
2023-11-29 03:13:55 -08:00
} from 'n8n-workflow' ;
import { getTemplateNoticeField } from '../../../utils/sharedFields' ;
2024-02-26 05:35:00 -08:00
import { promptTypeOptions , textInput } from '../../../utils/descriptions' ;
2023-11-29 03:13:55 -08:00
import { conversationalAgentProperties } from './agents/ConversationalAgent/description' ;
import { conversationalAgentExecute } from './agents/ConversationalAgent/execute' ;
import { openAiFunctionsAgentProperties } from './agents/OpenAiFunctionsAgent/description' ;
import { openAiFunctionsAgentExecute } from './agents/OpenAiFunctionsAgent/execute' ;
import { planAndExecuteAgentProperties } from './agents/PlanAndExecuteAgent/description' ;
import { planAndExecuteAgentExecute } from './agents/PlanAndExecuteAgent/execute' ;
import { reActAgentAgentProperties } from './agents/ReActAgent/description' ;
import { reActAgentAgentExecute } from './agents/ReActAgent/execute' ;
import { sqlAgentAgentProperties } from './agents/SqlAgent/description' ;
import { sqlAgentAgentExecute } from './agents/SqlAgent/execute' ;
2024-05-15 03:02:21 -07:00
import { toolsAgentProperties } from './agents/ToolsAgent/description' ;
import { toolsAgentExecute } from './agents/ToolsAgent/execute' ;
2024-02-26 05:35:00 -08:00
2023-11-29 03:13:55 -08:00
// Function used in the inputs expression to figure out which inputs to
// display based on the agent type
function getInputs (
2024-05-15 03:02:21 -07:00
agent : 'toolsAgent' | 'conversationalAgent' | 'openAiFunctionsAgent' | 'reActAgent' | 'sqlAgent' ,
2024-02-21 05:59:37 -08:00
hasOutputParser? : boolean ,
2023-11-29 03:13:55 -08:00
) : Array < ConnectionTypes | INodeInputConfiguration > {
interface SpecialInput {
type : ConnectionTypes ;
filter? : INodeInputFilter ;
2024-02-21 05:59:37 -08:00
required? : boolean ;
2023-11-29 03:13:55 -08:00
}
const getInputData = (
inputs : SpecialInput [ ] ,
) : Array < ConnectionTypes | INodeInputConfiguration > = > {
const displayNames : { [ key : string ] : string } = {
[ NodeConnectionType . AiLanguageModel ] : 'Model' ,
[ NodeConnectionType . AiMemory ] : 'Memory' ,
[ NodeConnectionType . AiTool ] : 'Tool' ,
[ NodeConnectionType . AiOutputParser ] : 'Output Parser' ,
} ;
2024-05-22 08:40:52 -07:00
return inputs . map ( ( { type , filter } ) = > {
2023-11-29 03:13:55 -08:00
const input : INodeInputConfiguration = {
type ,
displayName : type in displayNames ? displayNames [ type ] : undefined ,
required : type === NodeConnectionType . AiLanguageModel ,
maxConnections : [ NodeConnectionType . AiLanguageModel , NodeConnectionType . AiMemory ] . includes (
type as NodeConnectionType ,
)
? 1
: undefined ,
} ;
if ( filter ) {
input . filter = filter ;
}
return input ;
} ) ;
} ;
let specialInputs : SpecialInput [ ] = [ ] ;
if ( agent === 'conversationalAgent' ) {
specialInputs = [
{
type : NodeConnectionType . AiLanguageModel ,
filter : {
nodes : [
'@n8n/n8n-nodes-langchain.lmChatAnthropic' ,
2024-04-30 00:37:30 -07:00
'@n8n/n8n-nodes-langchain.lmChatGroq' ,
2023-11-29 03:13:55 -08:00
'@n8n/n8n-nodes-langchain.lmChatOllama' ,
'@n8n/n8n-nodes-langchain.lmChatOpenAi' ,
'@n8n/n8n-nodes-langchain.lmChatGooglePalm' ,
2024-04-15 04:56:44 -07:00
'@n8n/n8n-nodes-langchain.lmChatGoogleGemini' ,
2024-01-15 00:13:54 -08:00
'@n8n/n8n-nodes-langchain.lmChatMistralCloud' ,
2024-02-21 05:57:21 -08:00
'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi' ,
2023-11-29 03:13:55 -08:00
] ,
} ,
} ,
{
type : NodeConnectionType . AiMemory ,
} ,
{
type : NodeConnectionType . AiTool ,
} ,
{
type : NodeConnectionType . AiOutputParser ,
} ,
] ;
2024-05-15 03:02:21 -07:00
} else if ( agent === 'toolsAgent' ) {
specialInputs = [
{
type : NodeConnectionType . AiLanguageModel ,
filter : {
nodes : [
'@n8n/n8n-nodes-langchain.lmChatAnthropic' ,
'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi' ,
'@n8n/n8n-nodes-langchain.lmChatMistralCloud' ,
'@n8n/n8n-nodes-langchain.lmChatOpenAi' ,
'@n8n/n8n-nodes-langchain.lmChatGroq' ,
] ,
} ,
} ,
{
type : NodeConnectionType . AiMemory ,
} ,
{
type : NodeConnectionType . AiTool ,
required : true ,
} ,
{
type : NodeConnectionType . AiOutputParser ,
} ,
] ;
2023-11-29 03:13:55 -08:00
} else if ( agent === 'openAiFunctionsAgent' ) {
specialInputs = [
{
type : NodeConnectionType . AiLanguageModel ,
filter : {
2024-02-23 00:08:51 -08:00
nodes : [
'@n8n/n8n-nodes-langchain.lmChatOpenAi' ,
'@n8n/n8n-nodes-langchain.lmChatAzureOpenAi' ,
] ,
2023-11-29 03:13:55 -08:00
} ,
} ,
{
type : NodeConnectionType . AiMemory ,
} ,
{
type : NodeConnectionType . AiTool ,
2024-02-21 05:59:37 -08:00
required : true ,
2023-11-29 03:13:55 -08:00
} ,
{
type : NodeConnectionType . AiOutputParser ,
} ,
] ;
} else if ( agent === 'reActAgent' ) {
specialInputs = [
{
type : NodeConnectionType . AiLanguageModel ,
} ,
{
type : NodeConnectionType . AiTool ,
} ,
{
type : NodeConnectionType . AiOutputParser ,
} ,
] ;
} else if ( agent === 'sqlAgent' ) {
specialInputs = [
{
type : NodeConnectionType . AiLanguageModel ,
} ,
2024-02-26 05:35:00 -08:00
{
type : NodeConnectionType . AiMemory ,
} ,
2023-11-29 03:13:55 -08:00
] ;
} else if ( agent === 'planAndExecuteAgent' ) {
specialInputs = [
{
type : NodeConnectionType . AiLanguageModel ,
} ,
{
type : NodeConnectionType . AiTool ,
} ,
{
type : NodeConnectionType . AiOutputParser ,
} ,
] ;
}
2024-02-21 05:59:37 -08:00
if ( hasOutputParser === false ) {
specialInputs = specialInputs . filter (
( input ) = > input . type !== NodeConnectionType . AiOutputParser ,
) ;
}
2023-11-29 03:13:55 -08:00
return [ NodeConnectionType . Main , . . . getInputData ( specialInputs ) ] ;
}
2024-05-15 03:02:21 -07:00
const agentTypeProperty : INodeProperties = {
displayName : 'Agent' ,
name : 'agent' ,
type : 'options' ,
noDataExpression : true ,
2024-06-05 05:39:20 -07:00
// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items
2024-05-15 03:02:21 -07:00
options : [
2024-06-05 05:39:20 -07:00
{
name : 'Tools Agent' ,
value : 'toolsAgent' ,
description :
'Utilized unified Tool calling interface to select the appropriate tools and argument for execution' ,
} ,
2024-05-15 03:02:21 -07:00
{
name : 'Conversational Agent' ,
value : 'conversationalAgent' ,
description :
'Selects tools to accomplish its task and uses memory to recall previous conversations' ,
} ,
{
name : 'OpenAI Functions Agent' ,
value : 'openAiFunctionsAgent' ,
description :
"Utilizes OpenAI's Function Calling feature to select the appropriate tool and arguments for execution" ,
} ,
{
name : 'Plan and Execute Agent' ,
value : 'planAndExecuteAgent' ,
description :
'Plan and execute agents accomplish an objective by first planning what to do, then executing the sub tasks' ,
} ,
{
name : 'ReAct Agent' ,
value : 'reActAgent' ,
description : 'Strategically select tools to accomplish a given task' ,
} ,
{
name : 'SQL Agent' ,
value : 'sqlAgent' ,
description : 'Answers questions about data in an SQL database' ,
} ,
] ,
default : '' ,
} ;
2023-11-29 03:13:55 -08:00
export class Agent implements INodeType {
description : INodeTypeDescription = {
displayName : 'AI Agent' ,
name : 'agent' ,
icon : 'fa:robot' ,
2024-06-06 04:34:30 -07:00
iconColor : 'black' ,
2023-11-29 03:13:55 -08:00
group : [ 'transform' ] ,
2024-05-15 03:02:21 -07:00
version : [ 1 , 1.1 , 1.2 , 1.3 , 1.4 , 1.5 , 1.6 ] ,
2023-11-29 03:13:55 -08:00
description : 'Generates an action plan and executes it. Can use external tools.' ,
subtitle :
2024-05-15 03:02:21 -07:00
"={{ { toolsAgent: 'Tools Agent', conversationalAgent: 'Conversational Agent', openAiFunctionsAgent: 'OpenAI Functions Agent', reActAgent: 'ReAct Agent', sqlAgent: 'SQL Agent', planAndExecuteAgent: 'Plan and Execute Agent' }[$parameter.agent] }}" ,
2023-11-29 03:13:55 -08:00
defaults : {
name : 'AI Agent' ,
color : '#404040' ,
} ,
codex : {
alias : [ 'LangChain' ] ,
categories : [ 'AI' ] ,
subcategories : {
2024-05-30 07:53:33 -07:00
AI : [ 'Agents' , 'Root Nodes' ] ,
2023-11-29 03:13:55 -08:00
} ,
resources : {
primaryDocumentation : [
{
url : 'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.agent/' ,
} ,
] ,
} ,
} ,
2024-02-21 05:59:37 -08:00
inputs : ` ={{
( ( agent , hasOutputParser ) = > {
$ { getInputs . toString ( ) } ;
return getInputs ( agent , hasOutputParser )
} ) ( $parameter . agent , $parameter . hasOutputParser === undefined || $parameter . hasOutputParser === true )
} } ` ,
2023-11-29 03:13:55 -08:00
outputs : [ NodeConnectionType . Main ] ,
credentials : [
{
// eslint-disable-next-line n8n-nodes-base/node-class-description-credentials-name-unsuffixed
name : 'mySql' ,
required : true ,
testedBy : 'mysqlConnectionTest' ,
displayOptions : {
show : {
agent : [ 'sqlAgent' ] ,
'/dataSource' : [ 'mysql' ] ,
} ,
} ,
} ,
{
name : 'postgres' ,
required : true ,
displayOptions : {
show : {
agent : [ 'sqlAgent' ] ,
'/dataSource' : [ 'postgres' ] ,
} ,
} ,
} ,
] ,
properties : [
{
. . . getTemplateNoticeField ( 1954 ) ,
displayOptions : {
show : {
agent : [ 'conversationalAgent' ] ,
} ,
} ,
} ,
2024-05-15 03:02:21 -07:00
// Make Conversational Agent the default agent for versions 1.5 and below
2023-11-29 03:13:55 -08:00
{
2024-05-15 03:02:21 -07:00
. . . agentTypeProperty ,
2024-06-13 03:37:30 -07:00
options : agentTypeProperty?.options?.filter (
( o ) = > 'value' in o && o . value !== 'toolsAgent' ,
) ,
2024-05-15 03:02:21 -07:00
displayOptions : { show : { '@version' : [ { _cnd : { lte : 1.5 } } ] } } ,
2023-11-29 03:13:55 -08:00
default : 'conversationalAgent' ,
} ,
2024-05-15 03:02:21 -07:00
// Make Tools Agent the default agent for versions 1.6 and above
{
. . . agentTypeProperty ,
displayOptions : { show : { '@version' : [ { _cnd : { gte : 1.6 } } ] } } ,
default : 'toolsAgent' ,
} ,
2024-02-21 05:59:37 -08:00
{
2024-02-26 05:35:00 -08:00
. . . promptTypeOptions ,
2024-02-21 05:59:37 -08:00
displayOptions : {
hide : {
'@version' : [ { _cnd : { lte : 1.2 } } ] ,
2024-02-26 05:35:00 -08:00
agent : [ 'sqlAgent' ] ,
2024-02-21 05:59:37 -08:00
} ,
} ,
} ,
{
2024-02-26 05:35:00 -08:00
. . . textInput ,
2024-02-21 05:59:37 -08:00
displayOptions : {
show : {
promptType : [ 'define' ] ,
} ,
2024-02-26 05:35:00 -08:00
hide : {
agent : [ 'sqlAgent' ] ,
} ,
2024-02-21 05:59:37 -08:00
} ,
} ,
{
displayName : 'Require Specific Output Format' ,
name : 'hasOutputParser' ,
type : 'boolean' ,
default : false ,
2024-03-11 02:34:59 -07:00
noDataExpression : true ,
2024-02-21 05:59:37 -08:00
displayOptions : {
hide : {
'@version' : [ { _cnd : { lte : 1.2 } } ] ,
agent : [ 'sqlAgent' ] ,
} ,
} ,
} ,
{
displayName : ` Connect an <a data-action='openSelectiveNodeCreator' data-action-parameter-connectiontype=' ${ NodeConnectionType . AiOutputParser } '>output parser</a> on the canvas to specify the output format you require ` ,
name : 'notice' ,
type : 'notice' ,
default : '' ,
displayOptions : {
show : {
hasOutputParser : [ true ] ,
} ,
} ,
} ,
2023-11-29 03:13:55 -08:00
2024-05-15 03:02:21 -07:00
. . . toolsAgentProperties ,
2023-11-29 03:13:55 -08:00
. . . conversationalAgentProperties ,
. . . openAiFunctionsAgentProperties ,
. . . reActAgentAgentProperties ,
. . . sqlAgentAgentProperties ,
. . . planAndExecuteAgentProperties ,
] ,
} ;
async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
const agentType = this . getNodeParameter ( 'agent' , 0 , '' ) as string ;
2024-02-29 03:28:38 -08:00
const nodeVersion = this . getNode ( ) . typeVersion ;
2023-11-29 03:13:55 -08:00
if ( agentType === 'conversationalAgent' ) {
2024-02-29 03:28:38 -08:00
return await conversationalAgentExecute . call ( this , nodeVersion ) ;
2024-05-15 03:02:21 -07:00
} else if ( agentType === 'toolsAgent' ) {
2024-05-22 08:40:52 -07:00
return await toolsAgentExecute . call ( this ) ;
2023-11-29 03:13:55 -08:00
} else if ( agentType === 'openAiFunctionsAgent' ) {
2024-02-29 03:28:38 -08:00
return await openAiFunctionsAgentExecute . call ( this , nodeVersion ) ;
2023-11-29 03:13:55 -08:00
} else if ( agentType === 'reActAgent' ) {
2024-02-29 03:28:38 -08:00
return await reActAgentAgentExecute . call ( this , nodeVersion ) ;
2023-11-29 03:13:55 -08:00
} else if ( agentType === 'sqlAgent' ) {
2024-05-22 08:40:52 -07:00
return await sqlAgentAgentExecute . call ( this ) ;
2023-11-29 03:13:55 -08:00
} else if ( agentType === 'planAndExecuteAgent' ) {
2024-02-29 03:28:38 -08:00
return await planAndExecuteAgentExecute . call ( this , nodeVersion ) ;
2023-11-29 03:13:55 -08:00
}
throw new NodeOperationError ( this . getNode ( ) , ` The agent type " ${ agentType } " is not supported ` ) ;
}
}