@n8n/n8n-nodes-langchain 1.91.0 → 1.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/credentials/AnthropicApi.credentials.js +8 -1
  2. package/dist/credentials/AnthropicApi.credentials.js.map +1 -1
  3. package/dist/credentials/AzureEntraCognitiveServicesOAuth2Api.credentials.js +150 -0
  4. package/dist/credentials/AzureEntraCognitiveServicesOAuth2Api.credentials.js.map +1 -0
  5. package/dist/known/credentials.json +10 -0
  6. package/dist/nodes/agents/Agent/agents/ToolsAgent/description.js +23 -0
  7. package/dist/nodes/agents/Agent/agents/ToolsAgent/description.js.map +1 -1
  8. package/dist/nodes/agents/Agent/agents/ToolsAgent/execute.js +28 -13
  9. package/dist/nodes/agents/Agent/agents/ToolsAgent/execute.js.map +1 -1
  10. package/dist/nodes/chains/ChainLLM/ChainLlm.node.js +39 -21
  11. package/dist/nodes/chains/ChainLLM/ChainLlm.node.js.map +1 -1
  12. package/dist/nodes/chains/ChainLLM/methods/config.js +24 -0
  13. package/dist/nodes/chains/ChainLLM/methods/config.js.map +1 -1
  14. package/dist/nodes/chains/ChainRetrievalQA/ChainRetrievalQa.node.js +55 -15
  15. package/dist/nodes/chains/ChainRetrievalQA/ChainRetrievalQa.node.js.map +1 -1
  16. package/dist/nodes/chains/ChainSummarization/V2/ChainSummarizationV2.node.js +54 -11
  17. package/dist/nodes/chains/ChainSummarization/V2/ChainSummarizationV2.node.js.map +1 -1
  18. package/dist/nodes/chains/InformationExtractor/InformationExtractor.node.js +66 -24
  19. package/dist/nodes/chains/InformationExtractor/InformationExtractor.node.js.map +1 -1
  20. package/dist/nodes/chains/SentimentAnalysis/SentimentAnalysis.node.js +86 -27
  21. package/dist/nodes/chains/SentimentAnalysis/SentimentAnalysis.node.js.map +1 -1
  22. package/dist/nodes/chains/TextClassifier/TextClassifier.node.js +81 -47
  23. package/dist/nodes/chains/TextClassifier/TextClassifier.node.js.map +1 -1
  24. package/dist/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.js +5 -1
  25. package/dist/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.js.map +1 -1
  26. package/dist/nodes/llms/LMChatAnthropic/methods/searchModels.js +3 -1
  27. package/dist/nodes/llms/LMChatAnthropic/methods/searchModels.js.map +1 -1
  28. package/dist/nodes/llms/LmChatAzureOpenAi/LmChatAzureOpenAi.node.js +63 -123
  29. package/dist/nodes/llms/LmChatAzureOpenAi/LmChatAzureOpenAi.node.js.map +1 -1
  30. package/dist/nodes/llms/LmChatAzureOpenAi/credentials/N8nOAuth2TokenCredential.js +61 -0
  31. package/dist/nodes/llms/LmChatAzureOpenAi/credentials/N8nOAuth2TokenCredential.js.map +1 -0
  32. package/dist/nodes/llms/LmChatAzureOpenAi/credentials/api-key.js +53 -0
  33. package/dist/nodes/llms/LmChatAzureOpenAi/credentials/api-key.js.map +1 -0
  34. package/dist/nodes/llms/LmChatAzureOpenAi/credentials/oauth2.js +54 -0
  35. package/dist/nodes/llms/LmChatAzureOpenAi/credentials/oauth2.js.map +1 -0
  36. package/dist/nodes/llms/LmChatAzureOpenAi/properties.js +155 -0
  37. package/dist/nodes/llms/LmChatAzureOpenAi/properties.js.map +1 -0
  38. package/dist/nodes/llms/LmChatAzureOpenAi/types.js +42 -0
  39. package/dist/nodes/llms/LmChatAzureOpenAi/types.js.map +1 -0
  40. package/dist/types/credentials.json +2 -1
  41. package/dist/types/nodes.json +8 -8
  42. package/package.json +8 -5
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../nodes/chains/ChainLLM/methods/config.ts"],"sourcesContent":["import {\n\tAIMessagePromptTemplate,\n\tHumanMessagePromptTemplate,\n\tSystemMessagePromptTemplate,\n} from '@langchain/core/prompts';\nimport type { IDataObject, INodeInputConfiguration, INodeProperties } from 'n8n-workflow';\nimport { NodeConnectionTypes } from 'n8n-workflow';\n\nimport { promptTypeOptions, textFromPreviousNode } from '@utils/descriptions';\nimport { getTemplateNoticeField } from '@utils/sharedFields';\n\n/**\n * Dynamic input configuration generation based on node parameters\n */\nexport function getInputs(parameters: IDataObject) {\n\tconst inputs: INodeInputConfiguration[] = [\n\t\t{ displayName: '', type: 'main' },\n\t\t{\n\t\t\tdisplayName: 'Model',\n\t\t\tmaxConnections: 1,\n\t\t\ttype: 'ai_languageModel',\n\t\t\trequired: true,\n\t\t},\n\t];\n\n\t// If `hasOutputParser` is undefined it must be version 1.3 or earlier so we\n\t// always add the output parser input\n\tconst hasOutputParser = parameters?.hasOutputParser;\n\tif (hasOutputParser === undefined || hasOutputParser === true) {\n\t\tinputs.push({\n\t\t\tdisplayName: 'Output Parser',\n\t\t\ttype: 'ai_outputParser',\n\t\t\tmaxConnections: 1,\n\t\t\trequired: false,\n\t\t});\n\t}\n\n\treturn inputs;\n}\n\n/**\n * Node properties configuration\n */\nexport const nodeProperties: INodeProperties[] = [\n\tgetTemplateNoticeField(1978),\n\t{\n\t\tdisplayName: 'Prompt',\n\t\tname: 'prompt',\n\t\ttype: 'string',\n\t\trequired: true,\n\t\tdefault: '={{ $json.input }}',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\t'@version': [1],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tdisplayName: 'Prompt',\n\t\tname: 'prompt',\n\t\ttype: 'string',\n\t\trequired: true,\n\t\tdefault: '={{ $json.chat_input }}',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\t'@version': [1.1, 1.2],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tdisplayName: 'Prompt',\n\t\tname: 'prompt',\n\t\ttype: 'string',\n\t\trequired: true,\n\t\tdefault: '={{ $json.chatInput }}',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\t'@version': [1.3],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\t...promptTypeOptions,\n\t\tdisplayOptions: {\n\t\t\thide: {\n\t\t\t\t'@version': [1, 1.1, 1.2, 1.3],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\t...textFromPreviousNode,\n\t\tdisplayOptions: { show: { promptType: ['auto'], '@version': [{ _cnd: { gte: 1.5 } }] } },\n\t},\n\t{\n\t\tdisplayName: 'Prompt (User Message)',\n\t\tname: 'text',\n\t\ttype: 'string',\n\t\trequired: true,\n\t\tdefault: '',\n\t\tplaceholder: 'e.g. Hello, how can you help me?',\n\t\ttypeOptions: {\n\t\t\trows: 2,\n\t\t},\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\tpromptType: ['define'],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tdisplayName: 'Require Specific Output Format',\n\t\tname: 'hasOutputParser',\n\t\ttype: 'boolean',\n\t\tdefault: false,\n\t\tnoDataExpression: true,\n\t\tdisplayOptions: {\n\t\t\thide: {\n\t\t\t\t'@version': [1, 1.1, 1.3],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tdisplayName: 'Chat Messages (if Using a Chat Model)',\n\t\tname: 'messages',\n\t\ttype: 'fixedCollection',\n\t\ttypeOptions: {\n\t\t\tmultipleValues: true,\n\t\t},\n\t\tdefault: {},\n\t\tplaceholder: 'Add prompt',\n\t\toptions: [\n\t\t\t{\n\t\t\t\tname: 'messageValues',\n\t\t\t\tdisplayName: 'Prompt',\n\t\t\t\tvalues: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Type Name or ID',\n\t\t\t\t\t\tname: 'type',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'AI',\n\t\t\t\t\t\t\t\tvalue: AIMessagePromptTemplate.lc_name(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'System',\n\t\t\t\t\t\t\t\tvalue: SystemMessagePromptTemplate.lc_name(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'User',\n\t\t\t\t\t\t\t\tvalue: HumanMessagePromptTemplate.lc_name(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: SystemMessagePromptTemplate.lc_name(),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Message Type',\n\t\t\t\t\t\tname: 'messageType',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\ttype: [HumanMessagePromptTemplate.lc_name()],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Text',\n\t\t\t\t\t\t\t\tvalue: 'text',\n\t\t\t\t\t\t\t\tdescription: 'Simple text message',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Image (Binary)',\n\t\t\t\t\t\t\t\tvalue: 'imageBinary',\n\t\t\t\t\t\t\t\tdescription: 'Process the binary input from the previous node',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Image (URL)',\n\t\t\t\t\t\t\t\tvalue: 'imageUrl',\n\t\t\t\t\t\t\t\tdescription: 'Process the image from the specified URL',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: 'text',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Image Data Field Name',\n\t\t\t\t\t\tname: 'binaryImageDataKey',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdefault: 'data',\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"The name of the field in the chain's input that contains the binary image file to be processed\",\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tmessageType: ['imageBinary'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Image URL',\n\t\t\t\t\t\tname: 'imageUrl',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tdescription: 'URL to the image to be processed',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tmessageType: ['imageUrl'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Image Details',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Control how the model processes the image and generates its textual understanding',\n\t\t\t\t\t\tname: 'imageDetail',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\ttype: [HumanMessagePromptTemplate.lc_name()],\n\t\t\t\t\t\t\t\tmessageType: ['imageBinary', 'imageUrl'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Auto',\n\t\t\t\t\t\t\t\tvalue: 'auto',\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t'Model will use the auto setting which will look at the image input size and decide if it should use the low or high setting',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Low',\n\t\t\t\t\t\t\t\tvalue: 'low',\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t'The model will receive a low-res 512px x 512px version of the image, and represent the image with a budget of 65 tokens. This allows the API to return faster responses and consume fewer input tokens for use cases that do not require high detail.',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'High',\n\t\t\t\t\t\t\t\tvalue: 'high',\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t'Allows the model to see the low res image and then creates detailed crops of input images as 512px squares based on the input image size. Each of the detailed crops uses twice the token budget (65 tokens) for a total of 129 tokens.',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: 'auto',\n\t\t\t\t\t},\n\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Message',\n\t\t\t\t\t\tname: 'message',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tmessageType: ['imageBinary', 'imageUrl'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tdisplayName: `Connect an <a data-action='openSelectiveNodeCreator' data-action-parameter-connectiontype='${NodeConnectionTypes.AiOutputParser}'>output parser</a> on the canvas to specify the output format you require`,\n\t\tname: 'notice',\n\t\ttype: 'notice',\n\t\tdefault: '',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\thasOutputParser: [true],\n\t\t\t},\n\t\t},\n\t},\n];\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../nodes/chains/ChainLLM/methods/config.ts"],"sourcesContent":["import {\n\tAIMessagePromptTemplate,\n\tHumanMessagePromptTemplate,\n\tSystemMessagePromptTemplate,\n} from '@langchain/core/prompts';\nimport type { IDataObject, INodeInputConfiguration, INodeProperties } from 'n8n-workflow';\nimport { NodeConnectionTypes } from 'n8n-workflow';\n\nimport { promptTypeOptions, textFromPreviousNode } from '@utils/descriptions';\nimport { getTemplateNoticeField } from '@utils/sharedFields';\n\n/**\n * Dynamic input configuration generation based on node parameters\n */\nexport function getInputs(parameters: IDataObject) {\n\tconst inputs: INodeInputConfiguration[] = [\n\t\t{ displayName: '', type: 'main' },\n\t\t{\n\t\t\tdisplayName: 'Model',\n\t\t\tmaxConnections: 1,\n\t\t\ttype: 'ai_languageModel',\n\t\t\trequired: true,\n\t\t},\n\t];\n\n\t// If `hasOutputParser` is undefined it must be version 1.3 or earlier so we\n\t// always add the output parser input\n\tconst hasOutputParser = parameters?.hasOutputParser;\n\tif (hasOutputParser === undefined || hasOutputParser === true) {\n\t\tinputs.push({\n\t\t\tdisplayName: 'Output Parser',\n\t\t\ttype: 'ai_outputParser',\n\t\t\tmaxConnections: 1,\n\t\t\trequired: false,\n\t\t});\n\t}\n\n\treturn inputs;\n}\n\n/**\n * Node properties configuration\n */\nexport const nodeProperties: INodeProperties[] = [\n\tgetTemplateNoticeField(1978),\n\t{\n\t\tdisplayName: 'Prompt',\n\t\tname: 'prompt',\n\t\ttype: 'string',\n\t\trequired: true,\n\t\tdefault: '={{ $json.input }}',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\t'@version': [1],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tdisplayName: 'Prompt',\n\t\tname: 'prompt',\n\t\ttype: 'string',\n\t\trequired: true,\n\t\tdefault: '={{ $json.chat_input }}',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\t'@version': [1.1, 1.2],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tdisplayName: 'Prompt',\n\t\tname: 'prompt',\n\t\ttype: 'string',\n\t\trequired: true,\n\t\tdefault: '={{ $json.chatInput }}',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\t'@version': [1.3],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\t...promptTypeOptions,\n\t\tdisplayOptions: {\n\t\t\thide: {\n\t\t\t\t'@version': [1, 1.1, 1.2, 1.3],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\t...textFromPreviousNode,\n\t\tdisplayOptions: { show: { promptType: ['auto'], '@version': [{ _cnd: { gte: 1.5 } }] } },\n\t},\n\t{\n\t\tdisplayName: 'Prompt (User Message)',\n\t\tname: 'text',\n\t\ttype: 'string',\n\t\trequired: true,\n\t\tdefault: '',\n\t\tplaceholder: 'e.g. Hello, how can you help me?',\n\t\ttypeOptions: {\n\t\t\trows: 2,\n\t\t},\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\tpromptType: ['define'],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tdisplayName: 'Require Specific Output Format',\n\t\tname: 'hasOutputParser',\n\t\ttype: 'boolean',\n\t\tdefault: false,\n\t\tnoDataExpression: true,\n\t\tdisplayOptions: {\n\t\t\thide: {\n\t\t\t\t'@version': [1, 1.1, 1.3],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tdisplayName: 'Chat Messages (if Using a Chat Model)',\n\t\tname: 'messages',\n\t\ttype: 'fixedCollection',\n\t\ttypeOptions: {\n\t\t\tmultipleValues: true,\n\t\t},\n\t\tdefault: {},\n\t\tplaceholder: 'Add prompt',\n\t\toptions: [\n\t\t\t{\n\t\t\t\tname: 'messageValues',\n\t\t\t\tdisplayName: 'Prompt',\n\t\t\t\tvalues: [\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Type Name or ID',\n\t\t\t\t\t\tname: 'type',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'AI',\n\t\t\t\t\t\t\t\tvalue: AIMessagePromptTemplate.lc_name(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'System',\n\t\t\t\t\t\t\t\tvalue: SystemMessagePromptTemplate.lc_name(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'User',\n\t\t\t\t\t\t\t\tvalue: HumanMessagePromptTemplate.lc_name(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: SystemMessagePromptTemplate.lc_name(),\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Message Type',\n\t\t\t\t\t\tname: 'messageType',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\ttype: [HumanMessagePromptTemplate.lc_name()],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Text',\n\t\t\t\t\t\t\t\tvalue: 'text',\n\t\t\t\t\t\t\t\tdescription: 'Simple text message',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Image (Binary)',\n\t\t\t\t\t\t\t\tvalue: 'imageBinary',\n\t\t\t\t\t\t\t\tdescription: 'Process the binary input from the previous node',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Image (URL)',\n\t\t\t\t\t\t\t\tvalue: 'imageUrl',\n\t\t\t\t\t\t\t\tdescription: 'Process the image from the specified URL',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: 'text',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Image Data Field Name',\n\t\t\t\t\t\tname: 'binaryImageDataKey',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdefault: 'data',\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"The name of the field in the chain's input that contains the binary image file to be processed\",\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tmessageType: ['imageBinary'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Image URL',\n\t\t\t\t\t\tname: 'imageUrl',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tdescription: 'URL to the image to be processed',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\tmessageType: ['imageUrl'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Image Details',\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Control how the model processes the image and generates its textual understanding',\n\t\t\t\t\t\tname: 'imageDetail',\n\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\ttype: [HumanMessagePromptTemplate.lc_name()],\n\t\t\t\t\t\t\t\tmessageType: ['imageBinary', 'imageUrl'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Auto',\n\t\t\t\t\t\t\t\tvalue: 'auto',\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t'Model will use the auto setting which will look at the image input size and decide if it should use the low or high setting',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'Low',\n\t\t\t\t\t\t\t\tvalue: 'low',\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t'The model will receive a low-res 512px x 512px version of the image, and represent the image with a budget of 65 tokens. This allows the API to return faster responses and consume fewer input tokens for use cases that do not require high detail.',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tname: 'High',\n\t\t\t\t\t\t\t\tvalue: 'high',\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t'Allows the model to see the low res image and then creates detailed crops of input images as 512px squares based on the input image size. Each of the detailed crops uses twice the token budget (65 tokens) for a total of 129 tokens.',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tdefault: 'auto',\n\t\t\t\t\t},\n\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Message',\n\t\t\t\t\t\tname: 'message',\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\tmessageType: ['imageBinary', 'imageUrl'],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tdefault: '',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tdisplayName: `Connect an <a data-action='openSelectiveNodeCreator' data-action-parameter-connectiontype='${NodeConnectionTypes.AiOutputParser}'>output parser</a> on the canvas to specify the output format you require`,\n\t\tname: 'notice',\n\t\ttype: 'notice',\n\t\tdefault: '',\n\t\tdisplayOptions: {\n\t\t\tshow: {\n\t\t\t\thasOutputParser: [true],\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tdisplayName: 'Batch Processing',\n\t\tname: 'batching',\n\t\ttype: 'collection',\n\t\tplaceholder: 'Add Batch Processing Option',\n\t\tdescription: 'Batch processing options for rate limiting',\n\t\tdefault: {},\n\t\toptions: [\n\t\t\t{\n\t\t\t\tdisplayName: 'Batch Size',\n\t\t\t\tname: 'batchSize',\n\t\t\t\tdefault: 100,\n\t\t\t\ttype: 'number',\n\t\t\t\tdescription:\n\t\t\t\t\t'How many items to process in parallel. This is useful for rate limiting, but will impact the agents log output.',\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Delay Between Batches',\n\t\t\t\tname: 'delayBetweenBatches',\n\t\t\t\tdefault: 1000,\n\t\t\t\ttype: 'number',\n\t\t\t\tdescription: 'Delay in milliseconds between batches. This is useful for rate limiting.',\n\t\t\t},\n\t\t],\n\t},\n];\n"],"mappings":"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","names":[]}
@@ -180,6 +180,29 @@ class ChainRetrievalQa {
180
180
  "@version": [{ _cnd: { gte: 1.5 } }]
181
181
  }
182
182
  }
183
+ },
184
+ {
185
+ displayName: "Batch Processing",
186
+ name: "batching",
187
+ type: "collection",
188
+ description: "Batch processing options for rate limiting",
189
+ default: {},
190
+ options: [
191
+ {
192
+ displayName: "Batch Size",
193
+ name: "batchSize",
194
+ default: 100,
195
+ type: "number",
196
+ description: "How many items to process in parallel. This is useful for rate limiting."
197
+ },
198
+ {
199
+ displayName: "Delay Between Batches",
200
+ name: "delayBetweenBatches",
201
+ default: 0,
202
+ type: "number",
203
+ description: "Delay in milliseconds between batches. This is useful for rate limiting."
204
+ }
205
+ ]
183
206
  }
184
207
  ]
185
208
  }
@@ -189,9 +212,15 @@ class ChainRetrievalQa {
189
212
  async execute() {
190
213
  this.logger.debug("Executing Retrieval QA Chain");
191
214
  const items = this.getInputData();
215
+ const { batchSize, delayBetweenBatches } = this.getNodeParameter("options.batching", 0, {
216
+ batchSize: 100,
217
+ delayBetweenBatches: 0
218
+ });
192
219
  const returnData = [];
193
- for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
194
- try {
220
+ for (let i = 0; i < items.length; i += batchSize) {
221
+ const batch = items.slice(i, i + batchSize);
222
+ const batchPromises = batch.map(async (_item, batchIndex) => {
223
+ const itemIndex = i + batchIndex;
195
224
  const model = await this.getInputConnectionData(
196
225
  import_n8n_workflow.NodeConnectionTypes.AiLanguageModel,
197
226
  0
@@ -245,24 +274,35 @@ class ChainRetrievalQa {
245
274
  retriever
246
275
  });
247
276
  const tracingConfig = (0, import_tracing.getTracingConfig)(this);
248
- const response = await retrievalChain.withConfig(tracingConfig).invoke({ input: query }, { signal: this.getExecutionCancelSignal() });
249
- const answer = response.answer;
277
+ const result = await retrievalChain.withConfig(tracingConfig).invoke({ input: query }, { signal: this.getExecutionCancelSignal() });
278
+ return result;
279
+ });
280
+ const batchResults = await Promise.allSettled(batchPromises);
281
+ batchResults.forEach((response, index) => {
282
+ if (response.status === "rejected") {
283
+ const error = response.reason;
284
+ if (this.continueOnFail()) {
285
+ const metadata = (0, import_n8n_workflow.parseErrorMetadata)(error);
286
+ returnData.push({
287
+ json: { error: error.message },
288
+ pairedItem: { item: index },
289
+ metadata
290
+ });
291
+ return;
292
+ } else {
293
+ throw error;
294
+ }
295
+ }
296
+ const output = response.value;
297
+ const answer = output.answer;
250
298
  if (this.getNode().typeVersion >= 1.5) {
251
299
  returnData.push({ json: { response: answer } });
252
300
  } else {
253
301
  returnData.push({ json: { response: { text: answer } } });
254
302
  }
255
- } catch (error) {
256
- if (this.continueOnFail()) {
257
- const metadata = (0, import_n8n_workflow.parseErrorMetadata)(error);
258
- returnData.push({
259
- json: { error: error.message },
260
- pairedItem: { item: itemIndex },
261
- metadata
262
- });
263
- continue;
264
- }
265
- throw error;
303
+ });
304
+ if (i + batchSize < items.length && delayBetweenBatches > 0) {
305
+ await (0, import_n8n_workflow.sleep)(delayBetweenBatches);
266
306
  }
267
307
  }
268
308
  return [returnData];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../nodes/chains/ChainRetrievalQA/ChainRetrievalQa.node.ts"],"sourcesContent":["import type { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport {\n\tChatPromptTemplate,\n\tSystemMessagePromptTemplate,\n\tHumanMessagePromptTemplate,\n\tPromptTemplate,\n} from '@langchain/core/prompts';\nimport type { BaseRetriever } from '@langchain/core/retrievers';\nimport { createStuffDocumentsChain } from 'langchain/chains/combine_documents';\nimport { createRetrievalChain } from 'langchain/chains/retrieval';\nimport { NodeConnectionTypes, NodeOperationError, parseErrorMetadata } from 'n8n-workflow';\nimport {\n\ttype INodeProperties,\n\ttype IExecuteFunctions,\n\ttype INodeExecutionData,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n} from 'n8n-workflow';\n\nimport { promptTypeOptions, textFromPreviousNode } from '@utils/descriptions';\nimport { getPromptInputByType, isChatInstance } from '@utils/helpers';\nimport { getTemplateNoticeField } from '@utils/sharedFields';\nimport { getTracingConfig } from '@utils/tracing';\n\nconst SYSTEM_PROMPT_TEMPLATE = `You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question.\nIf you don't know the answer, just say that you don't know, don't try to make up an answer.\n----------------\nContext: {context}`;\n\n// Due to the refactoring in version 1.5, the variable name {question} needed to be changed to {input} in the prompt template.\nconst LEGACY_INPUT_TEMPLATE_KEY = 'question';\nconst INPUT_TEMPLATE_KEY = 'input';\n\nconst systemPromptOption: INodeProperties = {\n\tdisplayName: 'System Prompt Template',\n\tname: 'systemPromptTemplate',\n\ttype: 'string',\n\tdefault: SYSTEM_PROMPT_TEMPLATE,\n\ttypeOptions: {\n\t\trows: 6,\n\t},\n};\n\nexport class ChainRetrievalQa implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Question and Answer Chain',\n\t\tname: 'chainRetrievalQa',\n\t\ticon: 'fa:link',\n\t\ticonColor: 'black',\n\t\tgroup: ['transform'],\n\t\tversion: [1, 1.1, 1.2, 1.3, 1.4, 1.5],\n\t\tdescription: 'Answer questions about retrieved documents',\n\t\tdefaults: {\n\t\t\tname: 'Question and Answer Chain',\n\t\t\tcolor: '#909298',\n\t\t},\n\t\tcodex: {\n\t\t\talias: ['LangChain'],\n\t\t\tcategories: ['AI'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Chains', 'Root Nodes'],\n\t\t\t},\n\t\t\tresources: {\n\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t{\n\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainretrievalqa/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node\n\t\tinputs: [\n\t\t\tNodeConnectionTypes.Main,\n\t\t\t{\n\t\t\t\tdisplayName: 'Model',\n\t\t\t\tmaxConnections: 1,\n\t\t\t\ttype: NodeConnectionTypes.AiLanguageModel,\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Retriever',\n\t\t\t\tmaxConnections: 1,\n\t\t\t\ttype: NodeConnectionTypes.AiRetriever,\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [],\n\t\tproperties: [\n\t\t\tgetTemplateNoticeField(1960),\n\t\t\t{\n\t\t\t\tdisplayName: 'Query',\n\t\t\t\tname: 'query',\n\t\t\t\ttype: 'string',\n\t\t\t\trequired: true,\n\t\t\t\tdefault: '={{ $json.input }}',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Query',\n\t\t\t\tname: 'query',\n\t\t\t\ttype: 'string',\n\t\t\t\trequired: true,\n\t\t\t\tdefault: '={{ $json.chat_input }}',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1.1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Query',\n\t\t\t\tname: 'query',\n\t\t\t\ttype: 'string',\n\t\t\t\trequired: true,\n\t\t\t\tdefault: '={{ $json.chatInput }}',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1.2],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t...promptTypeOptions,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\thide: {\n\t\t\t\t\t\t'@version': [{ _cnd: { lte: 1.2 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t...textFromPreviousNode,\n\t\t\t\tdisplayOptions: { show: { promptType: ['auto'], '@version': [{ _cnd: { gte: 1.4 } }] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Prompt (User Message)',\n\t\t\t\tname: 'text',\n\t\t\t\ttype: 'string',\n\t\t\t\trequired: true,\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'e.g. Hello, how can you help me?',\n\t\t\t\ttypeOptions: {\n\t\t\t\t\trows: 2,\n\t\t\t\t},\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tpromptType: ['define'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\t...systemPromptOption,\n\t\t\t\t\t\tdescription: `Template string used for the system prompt. This should include the variable \\`{context}\\` for the provided context. For text completion models, you should also include the variable \\`{${LEGACY_INPUT_TEMPLATE_KEY}}\\` for the user’s query.`,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'@version': [{ _cnd: { lt: 1.5 } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t...systemPromptOption,\n\t\t\t\t\t\tdescription: `Template string used for the system prompt. This should include the variable \\`{context}\\` for the provided context. For text completion models, you should also include the variable \\`{${INPUT_TEMPLATE_KEY}}\\` for the user’s query.`,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.5 } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tthis.logger.debug('Executing Retrieval QA Chain');\n\n\t\tconst items = this.getInputData();\n\t\tconst returnData: INodeExecutionData[] = [];\n\n\t\t// Run for each item\n\t\tfor (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n\t\t\ttry {\n\t\t\t\tconst model = (await this.getInputConnectionData(\n\t\t\t\t\tNodeConnectionTypes.AiLanguageModel,\n\t\t\t\t\t0,\n\t\t\t\t)) as BaseLanguageModel;\n\n\t\t\t\tconst retriever = (await this.getInputConnectionData(\n\t\t\t\t\tNodeConnectionTypes.AiRetriever,\n\t\t\t\t\t0,\n\t\t\t\t)) as BaseRetriever;\n\n\t\t\t\tlet query;\n\n\t\t\t\tif (this.getNode().typeVersion <= 1.2) {\n\t\t\t\t\tquery = this.getNodeParameter('query', itemIndex) as string;\n\t\t\t\t} else {\n\t\t\t\t\tquery = getPromptInputByType({\n\t\t\t\t\t\tctx: this,\n\t\t\t\t\t\ti: itemIndex,\n\t\t\t\t\t\tinputKey: 'text',\n\t\t\t\t\t\tpromptTypeKey: 'promptType',\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (query === undefined) {\n\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'The ‘query‘ parameter is empty.');\n\t\t\t\t}\n\n\t\t\t\tconst options = this.getNodeParameter('options', itemIndex, {}) as {\n\t\t\t\t\tsystemPromptTemplate?: string;\n\t\t\t\t};\n\n\t\t\t\tlet templateText = options.systemPromptTemplate ?? SYSTEM_PROMPT_TEMPLATE;\n\n\t\t\t\t// Replace legacy input template key for versions 1.4 and below\n\t\t\t\tif (this.getNode().typeVersion < 1.5) {\n\t\t\t\t\ttemplateText = templateText.replace(\n\t\t\t\t\t\t`{${LEGACY_INPUT_TEMPLATE_KEY}}`,\n\t\t\t\t\t\t`{${INPUT_TEMPLATE_KEY}}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Create prompt template based on model type and user configuration\n\t\t\t\tlet promptTemplate;\n\t\t\t\tif (isChatInstance(model)) {\n\t\t\t\t\t// For chat models, create a chat prompt template with system and human messages\n\t\t\t\t\tconst messages = [\n\t\t\t\t\t\tSystemMessagePromptTemplate.fromTemplate(templateText),\n\t\t\t\t\t\tHumanMessagePromptTemplate.fromTemplate('{input}'),\n\t\t\t\t\t];\n\t\t\t\t\tpromptTemplate = ChatPromptTemplate.fromMessages(messages);\n\t\t\t\t} else {\n\t\t\t\t\t// For non-chat models, create a text prompt template with Question/Answer format\n\t\t\t\t\tconst questionSuffix =\n\t\t\t\t\t\toptions.systemPromptTemplate === undefined ? '\\n\\nQuestion: {input}\\nAnswer:' : '';\n\n\t\t\t\t\tpromptTemplate = new PromptTemplate({\n\t\t\t\t\t\ttemplate: templateText + questionSuffix,\n\t\t\t\t\t\tinputVariables: ['context', 'input'],\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Create the document chain that combines the retrieved documents\n\t\t\t\tconst combineDocsChain = await createStuffDocumentsChain({\n\t\t\t\t\tllm: model,\n\t\t\t\t\tprompt: promptTemplate,\n\t\t\t\t});\n\n\t\t\t\t// Create the retrieval chain that handles the retrieval and then passes to the combine docs chain\n\t\t\t\tconst retrievalChain = await createRetrievalChain({\n\t\t\t\t\tcombineDocsChain,\n\t\t\t\t\tretriever,\n\t\t\t\t});\n\n\t\t\t\t// Execute the chain with tracing config\n\t\t\t\tconst tracingConfig = getTracingConfig(this);\n\t\t\t\tconst response = await retrievalChain\n\t\t\t\t\t.withConfig(tracingConfig)\n\t\t\t\t\t.invoke({ input: query }, { signal: this.getExecutionCancelSignal() });\n\n\t\t\t\t// Get the answer from the response\n\t\t\t\tconst answer: string = response.answer;\n\t\t\t\tif (this.getNode().typeVersion >= 1.5) {\n\t\t\t\t\treturnData.push({ json: { response: answer } });\n\t\t\t\t} else {\n\t\t\t\t\t// Legacy format for versions 1.4 and below is { text: string }\n\t\t\t\t\treturnData.push({ json: { response: { text: answer } } });\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (this.continueOnFail()) {\n\t\t\t\t\tconst metadata = parseErrorMetadata(error);\n\t\t\t\t\treturnData.push({\n\t\t\t\t\t\tjson: { error: error.message },\n\t\t\t\t\t\tpairedItem: { item: itemIndex },\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\treturn [returnData];\n\t}\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../nodes/chains/ChainRetrievalQA/ChainRetrievalQa.node.ts"],"sourcesContent":["import type { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport {\n\tChatPromptTemplate,\n\tSystemMessagePromptTemplate,\n\tHumanMessagePromptTemplate,\n\tPromptTemplate,\n} from '@langchain/core/prompts';\nimport type { BaseRetriever } from '@langchain/core/retrievers';\nimport { createStuffDocumentsChain } from 'langchain/chains/combine_documents';\nimport { createRetrievalChain } from 'langchain/chains/retrieval';\nimport { NodeConnectionTypes, NodeOperationError, parseErrorMetadata, sleep } from 'n8n-workflow';\nimport {\n\ttype INodeProperties,\n\ttype IExecuteFunctions,\n\ttype INodeExecutionData,\n\ttype INodeType,\n\ttype INodeTypeDescription,\n} from 'n8n-workflow';\n\nimport { promptTypeOptions, textFromPreviousNode } from '@utils/descriptions';\nimport { getPromptInputByType, isChatInstance } from '@utils/helpers';\nimport { getTemplateNoticeField } from '@utils/sharedFields';\nimport { getTracingConfig } from '@utils/tracing';\n\nconst SYSTEM_PROMPT_TEMPLATE = `You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question.\nIf you don't know the answer, just say that you don't know, don't try to make up an answer.\n----------------\nContext: {context}`;\n\n// Due to the refactoring in version 1.5, the variable name {question} needed to be changed to {input} in the prompt template.\nconst LEGACY_INPUT_TEMPLATE_KEY = 'question';\nconst INPUT_TEMPLATE_KEY = 'input';\n\nconst systemPromptOption: INodeProperties = {\n\tdisplayName: 'System Prompt Template',\n\tname: 'systemPromptTemplate',\n\ttype: 'string',\n\tdefault: SYSTEM_PROMPT_TEMPLATE,\n\ttypeOptions: {\n\t\trows: 6,\n\t},\n};\n\nexport class ChainRetrievalQa implements INodeType {\n\tdescription: INodeTypeDescription = {\n\t\tdisplayName: 'Question and Answer Chain',\n\t\tname: 'chainRetrievalQa',\n\t\ticon: 'fa:link',\n\t\ticonColor: 'black',\n\t\tgroup: ['transform'],\n\t\tversion: [1, 1.1, 1.2, 1.3, 1.4, 1.5],\n\t\tdescription: 'Answer questions about retrieved documents',\n\t\tdefaults: {\n\t\t\tname: 'Question and Answer Chain',\n\t\t\tcolor: '#909298',\n\t\t},\n\t\tcodex: {\n\t\t\talias: ['LangChain'],\n\t\t\tcategories: ['AI'],\n\t\t\tsubcategories: {\n\t\t\t\tAI: ['Chains', 'Root Nodes'],\n\t\t\t},\n\t\t\tresources: {\n\t\t\t\tprimaryDocumentation: [\n\t\t\t\t\t{\n\t\t\t\t\t\turl: 'https://docs.n8n.io/integrations/builtin/cluster-nodes/root-nodes/n8n-nodes-langchain.chainretrievalqa/',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node\n\t\tinputs: [\n\t\t\tNodeConnectionTypes.Main,\n\t\t\t{\n\t\t\t\tdisplayName: 'Model',\n\t\t\t\tmaxConnections: 1,\n\t\t\t\ttype: NodeConnectionTypes.AiLanguageModel,\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Retriever',\n\t\t\t\tmaxConnections: 1,\n\t\t\t\ttype: NodeConnectionTypes.AiRetriever,\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t\toutputs: [NodeConnectionTypes.Main],\n\t\tcredentials: [],\n\t\tproperties: [\n\t\t\tgetTemplateNoticeField(1960),\n\t\t\t{\n\t\t\t\tdisplayName: 'Query',\n\t\t\t\tname: 'query',\n\t\t\t\ttype: 'string',\n\t\t\t\trequired: true,\n\t\t\t\tdefault: '={{ $json.input }}',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Query',\n\t\t\t\tname: 'query',\n\t\t\t\ttype: 'string',\n\t\t\t\trequired: true,\n\t\t\t\tdefault: '={{ $json.chat_input }}',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1.1],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Query',\n\t\t\t\tname: 'query',\n\t\t\t\ttype: 'string',\n\t\t\t\trequired: true,\n\t\t\t\tdefault: '={{ $json.chatInput }}',\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\t'@version': [1.2],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t...promptTypeOptions,\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\thide: {\n\t\t\t\t\t\t'@version': [{ _cnd: { lte: 1.2 } }],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\t...textFromPreviousNode,\n\t\t\t\tdisplayOptions: { show: { promptType: ['auto'], '@version': [{ _cnd: { gte: 1.4 } }] } },\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Prompt (User Message)',\n\t\t\t\tname: 'text',\n\t\t\t\ttype: 'string',\n\t\t\t\trequired: true,\n\t\t\t\tdefault: '',\n\t\t\t\tplaceholder: 'e.g. Hello, how can you help me?',\n\t\t\t\ttypeOptions: {\n\t\t\t\t\trows: 2,\n\t\t\t\t},\n\t\t\t\tdisplayOptions: {\n\t\t\t\t\tshow: {\n\t\t\t\t\t\tpromptType: ['define'],\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tdisplayName: 'Options',\n\t\t\t\tname: 'options',\n\t\t\t\ttype: 'collection',\n\t\t\t\tdefault: {},\n\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\toptions: [\n\t\t\t\t\t{\n\t\t\t\t\t\t...systemPromptOption,\n\t\t\t\t\t\tdescription: `Template string used for the system prompt. This should include the variable \\`{context}\\` for the provided context. For text completion models, you should also include the variable \\`{${LEGACY_INPUT_TEMPLATE_KEY}}\\` for the user’s query.`,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'@version': [{ _cnd: { lt: 1.5 } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t...systemPromptOption,\n\t\t\t\t\t\tdescription: `Template string used for the system prompt. This should include the variable \\`{context}\\` for the provided context. For text completion models, you should also include the variable \\`{${INPUT_TEMPLATE_KEY}}\\` for the user’s query.`,\n\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t'@version': [{ _cnd: { gte: 1.5 } }],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tdisplayName: 'Batch Processing',\n\t\t\t\t\t\tname: 'batching',\n\t\t\t\t\t\ttype: 'collection',\n\t\t\t\t\t\tdescription: 'Batch processing options for rate limiting',\n\t\t\t\t\t\tdefault: {},\n\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdisplayName: 'Batch Size',\n\t\t\t\t\t\t\t\tname: 'batchSize',\n\t\t\t\t\t\t\t\tdefault: 100,\n\t\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t'How many items to process in parallel. This is useful for rate limiting.',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdisplayName: 'Delay Between Batches',\n\t\t\t\t\t\t\t\tname: 'delayBetweenBatches',\n\t\t\t\t\t\t\t\tdefault: 0,\n\t\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t'Delay in milliseconds between batches. This is useful for rate limiting.',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tthis.logger.debug('Executing Retrieval QA Chain');\n\n\t\tconst items = this.getInputData();\n\t\tconst { batchSize, delayBetweenBatches } = this.getNodeParameter('options.batching', 0, {\n\t\t\tbatchSize: 100,\n\t\t\tdelayBetweenBatches: 0,\n\t\t}) as {\n\t\t\tbatchSize: number;\n\t\t\tdelayBetweenBatches: number;\n\t\t};\n\t\tconst returnData: INodeExecutionData[] = [];\n\n\t\tfor (let i = 0; i < items.length; i += batchSize) {\n\t\t\tconst batch = items.slice(i, i + batchSize);\n\t\t\tconst batchPromises = batch.map(async (_item, batchIndex) => {\n\t\t\t\tconst itemIndex = i + batchIndex;\n\n\t\t\t\tconst model = (await this.getInputConnectionData(\n\t\t\t\t\tNodeConnectionTypes.AiLanguageModel,\n\t\t\t\t\t0,\n\t\t\t\t)) as BaseLanguageModel;\n\n\t\t\t\tconst retriever = (await this.getInputConnectionData(\n\t\t\t\t\tNodeConnectionTypes.AiRetriever,\n\t\t\t\t\t0,\n\t\t\t\t)) as BaseRetriever;\n\n\t\t\t\tlet query;\n\n\t\t\t\tif (this.getNode().typeVersion <= 1.2) {\n\t\t\t\t\tquery = this.getNodeParameter('query', itemIndex) as string;\n\t\t\t\t} else {\n\t\t\t\t\tquery = getPromptInputByType({\n\t\t\t\t\t\tctx: this,\n\t\t\t\t\t\ti: itemIndex,\n\t\t\t\t\t\tinputKey: 'text',\n\t\t\t\t\t\tpromptTypeKey: 'promptType',\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (query === undefined) {\n\t\t\t\t\tthrow new NodeOperationError(this.getNode(), 'The ‘query‘ parameter is empty.');\n\t\t\t\t}\n\n\t\t\t\tconst options = this.getNodeParameter('options', itemIndex, {}) as {\n\t\t\t\t\tsystemPromptTemplate?: string;\n\t\t\t\t};\n\n\t\t\t\tlet templateText = options.systemPromptTemplate ?? SYSTEM_PROMPT_TEMPLATE;\n\n\t\t\t\t// Replace legacy input template key for versions 1.4 and below\n\t\t\t\tif (this.getNode().typeVersion < 1.5) {\n\t\t\t\t\ttemplateText = templateText.replace(\n\t\t\t\t\t\t`{${LEGACY_INPUT_TEMPLATE_KEY}}`,\n\t\t\t\t\t\t`{${INPUT_TEMPLATE_KEY}}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Create prompt template based on model type and user configuration\n\t\t\t\tlet promptTemplate;\n\t\t\t\tif (isChatInstance(model)) {\n\t\t\t\t\t// For chat models, create a chat prompt template with system and human messages\n\t\t\t\t\tconst messages = [\n\t\t\t\t\t\tSystemMessagePromptTemplate.fromTemplate(templateText),\n\t\t\t\t\t\tHumanMessagePromptTemplate.fromTemplate('{input}'),\n\t\t\t\t\t];\n\t\t\t\t\tpromptTemplate = ChatPromptTemplate.fromMessages(messages);\n\t\t\t\t} else {\n\t\t\t\t\t// For non-chat models, create a text prompt template with Question/Answer format\n\t\t\t\t\tconst questionSuffix =\n\t\t\t\t\t\toptions.systemPromptTemplate === undefined ? '\\n\\nQuestion: {input}\\nAnswer:' : '';\n\n\t\t\t\t\tpromptTemplate = new PromptTemplate({\n\t\t\t\t\t\ttemplate: templateText + questionSuffix,\n\t\t\t\t\t\tinputVariables: ['context', 'input'],\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Create the document chain that combines the retrieved documents\n\t\t\t\tconst combineDocsChain = await createStuffDocumentsChain({\n\t\t\t\t\tllm: model,\n\t\t\t\t\tprompt: promptTemplate,\n\t\t\t\t});\n\n\t\t\t\t// Create the retrieval chain that handles the retrieval and then passes to the combine docs chain\n\t\t\t\tconst retrievalChain = await createRetrievalChain({\n\t\t\t\t\tcombineDocsChain,\n\t\t\t\t\tretriever,\n\t\t\t\t});\n\n\t\t\t\t// Execute the chain with tracing config\n\t\t\t\tconst tracingConfig = getTracingConfig(this);\n\n\t\t\t\tconst result = await retrievalChain\n\t\t\t\t\t.withConfig(tracingConfig)\n\t\t\t\t\t.invoke({ input: query }, { signal: this.getExecutionCancelSignal() });\n\n\t\t\t\treturn result;\n\t\t\t});\n\n\t\t\tconst batchResults = await Promise.allSettled(batchPromises);\n\n\t\t\tbatchResults.forEach((response, index) => {\n\t\t\t\tif (response.status === 'rejected') {\n\t\t\t\t\tconst error = response.reason;\n\t\t\t\t\tif (this.continueOnFail()) {\n\t\t\t\t\t\tconst metadata = parseErrorMetadata(error);\n\t\t\t\t\t\treturnData.push({\n\t\t\t\t\t\t\tjson: { error: error.message },\n\t\t\t\t\t\t\tpairedItem: { item: index },\n\t\t\t\t\t\t\tmetadata,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst output = response.value;\n\t\t\t\tconst answer: string = output.answer;\n\t\t\t\tif (this.getNode().typeVersion >= 1.5) {\n\t\t\t\t\treturnData.push({ json: { response: answer } });\n\t\t\t\t} else {\n\t\t\t\t\t// Legacy format for versions 1.4 and below is { text: string }\n\t\t\t\t\treturnData.push({ json: { response: { text: answer } } });\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Add delay between batches if not the last batch\n\t\t\tif (i + batchSize < items.length && delayBetweenBatches > 0) {\n\t\t\t\tawait sleep(delayBetweenBatches);\n\t\t\t}\n\t\t}\n\n\t\treturn [returnData];\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -303,6 +303,29 @@ class ChainSummarizationV2 {
303
303
  ]
304
304
  }
305
305
  ]
306
+ },
307
+ {
308
+ displayName: "Batch Processing",
309
+ name: "batching",
310
+ type: "collection",
311
+ description: "Batch processing options for rate limiting",
312
+ default: {},
313
+ options: [
314
+ {
315
+ displayName: "Batch Size",
316
+ name: "batchSize",
317
+ default: 100,
318
+ type: "number",
319
+ description: "How many items to process in parallel. This is useful for rate limiting."
320
+ },
321
+ {
322
+ displayName: "Delay Between Batches",
323
+ name: "delayBetweenBatches",
324
+ default: 0,
325
+ type: "number",
326
+ description: "Delay in milliseconds between batches. This is useful for rate limiting."
327
+ }
328
+ ]
306
329
  }
307
330
  ]
308
331
  }
@@ -315,8 +338,14 @@ class ChainSummarizationV2 {
315
338
  const chunkingMode = this.getNodeParameter("chunkingMode", 0, "simple");
316
339
  const items = this.getInputData();
317
340
  const returnData = [];
318
- for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
319
- try {
341
+ const { batchSize, delayBetweenBatches } = this.getNodeParameter("options.batching", 0, {
342
+ batchSize: 100,
343
+ delayBetweenBatches: 0
344
+ });
345
+ for (let i = 0; i < items.length; i += batchSize) {
346
+ const batch = items.slice(i, i + batchSize);
347
+ const batchPromises = batch.map(async (_item, batchIndex) => {
348
+ const itemIndex = i + batchIndex;
320
349
  const model = await this.getInputConnectionData(
321
350
  import_n8n_workflow.NodeConnectionTypes.AiLanguageModel,
322
351
  0
@@ -333,6 +362,7 @@ class ChainSummarizationV2 {
333
362
  const chain = (0, import_chains.loadSummarizationChain)(model, chainArgs);
334
363
  const item = items[itemIndex];
335
364
  let processedDocuments;
365
+ let output = {};
336
366
  if (operationMode === "documentLoader") {
337
367
  const documentInput = await this.getInputConnectionData(
338
368
  import_n8n_workflow.NodeConnectionTypes.AiDocument,
@@ -340,10 +370,9 @@ class ChainSummarizationV2 {
340
370
  );
341
371
  const isN8nLoader = documentInput instanceof import_N8nJsonLoader.N8nJsonLoader || documentInput instanceof import_N8nBinaryLoader.N8nBinaryLoader;
342
372
  processedDocuments = isN8nLoader ? await documentInput.processItem(item, itemIndex) : documentInput;
343
- const response = await chain.withConfig((0, import_tracing.getTracingConfig)(this)).invoke({
373
+ output = await chain.withConfig((0, import_tracing.getTracingConfig)(this)).invoke({
344
374
  input_documents: processedDocuments
345
375
  });
346
- returnData.push({ json: { response } });
347
376
  }
348
377
  if (["nodeInputJson", "nodeInputBinary"].includes(operationMode)) {
349
378
  let textSplitter;
@@ -376,20 +405,34 @@ class ChainSummarizationV2 {
376
405
  processor = new import_N8nJsonLoader.N8nJsonLoader(this, "options.", textSplitter);
377
406
  }
378
407
  const processedItem = await processor.processItem(item, itemIndex);
379
- const response = await chain.invoke(
408
+ output = await chain.invoke(
380
409
  {
381
410
  input_documents: processedItem
382
411
  },
383
412
  { signal: this.getExecutionCancelSignal() }
384
413
  );
385
- returnData.push({ json: { response } });
386
414
  }
387
- } catch (error) {
388
- if (this.continueOnFail()) {
389
- returnData.push({ json: { error: error.message }, pairedItem: { item: itemIndex } });
390
- continue;
415
+ return output;
416
+ });
417
+ const batchResults = await Promise.allSettled(batchPromises);
418
+ batchResults.forEach((response, index) => {
419
+ if (response.status === "rejected") {
420
+ const error = response.reason;
421
+ if (this.continueOnFail()) {
422
+ returnData.push({
423
+ json: { error: error.message },
424
+ pairedItem: { item: i + index }
425
+ });
426
+ } else {
427
+ throw error;
428
+ }
429
+ } else {
430
+ const output = response.value;
431
+ returnData.push({ json: { output } });
391
432
  }
392
- throw error;
433
+ });
434
+ if (i + batchSize < items.length && delayBetweenBatches > 0) {
435
+ await (0, import_n8n_workflow.sleep)(delayBetweenBatches);
393
436
  }
394
437
  }
395
438
  return [returnData];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../nodes/chains/ChainSummarization/V2/ChainSummarizationV2.node.ts"],"sourcesContent":["import type { Document } from '@langchain/core/documents';\nimport type { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport type { TextSplitter } from '@langchain/textsplitters';\nimport { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';\nimport { loadSummarizationChain } from 'langchain/chains';\nimport type {\n\tINodeTypeBaseDescription,\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n\tIDataObject,\n\tINodeInputConfiguration,\n} from 'n8n-workflow';\nimport { NodeConnectionTypes } from 'n8n-workflow';\n\nimport { N8nBinaryLoader } from '@utils/N8nBinaryLoader';\nimport { N8nJsonLoader } from '@utils/N8nJsonLoader';\nimport { getTemplateNoticeField } from '@utils/sharedFields';\nimport { getTracingConfig } from '@utils/tracing';\n\nimport { getChainPromptsArgs } from '../helpers';\nimport { REFINE_PROMPT_TEMPLATE, DEFAULT_PROMPT_TEMPLATE } from '../prompt';\n\nfunction getInputs(parameters: IDataObject) {\n\tconst chunkingMode = parameters?.chunkingMode;\n\tconst operationMode = parameters?.operationMode;\n\tconst inputs: INodeInputConfiguration[] = [\n\t\t{ displayName: '', type: 'main' },\n\t\t{\n\t\t\tdisplayName: 'Model',\n\t\t\tmaxConnections: 1,\n\t\t\ttype: 'ai_languageModel',\n\t\t\trequired: true,\n\t\t},\n\t];\n\n\tif (operationMode === 'documentLoader') {\n\t\tinputs.push({\n\t\t\tdisplayName: 'Document',\n\t\t\ttype: 'ai_document',\n\t\t\trequired: true,\n\t\t\tmaxConnections: 1,\n\t\t});\n\t\treturn inputs;\n\t}\n\n\tif (chunkingMode === 'advanced') {\n\t\tinputs.push({\n\t\t\tdisplayName: 'Text Splitter',\n\t\t\ttype: 'ai_textSplitter',\n\t\t\trequired: false,\n\t\t\tmaxConnections: 1,\n\t\t});\n\t\treturn inputs;\n\t}\n\treturn inputs;\n}\n\nexport class ChainSummarizationV2 implements INodeType {\n\tdescription: INodeTypeDescription;\n\n\tconstructor(baseDescription: INodeTypeBaseDescription) {\n\t\tthis.description = {\n\t\t\t...baseDescription,\n\t\t\tversion: [2],\n\t\t\tdefaults: {\n\t\t\t\tname: 'Summarization Chain',\n\t\t\t\tcolor: '#909298',\n\t\t\t},\n\t\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node\n\t\t\tinputs: `={{ ((parameter) => { ${getInputs.toString()}; return getInputs(parameter) })($parameter) }}`,\n\t\t\toutputs: [NodeConnectionTypes.Main],\n\t\t\tcredentials: [],\n\t\t\tproperties: [\n\t\t\t\tgetTemplateNoticeField(1951),\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Data to Summarize',\n\t\t\t\t\tname: 'operationMode',\n\t\t\t\t\tnoDataExpression: true,\n\t\t\t\t\ttype: 'options',\n\t\t\t\t\tdescription: 'How to pass data into the summarization chain',\n\t\t\t\t\tdefault: 'nodeInputJson',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'Use Node Input (JSON)',\n\t\t\t\t\t\t\tvalue: 'nodeInputJson',\n\t\t\t\t\t\t\tdescription: 'Summarize the JSON data coming into this node from the previous one',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'Use Node Input (Binary)',\n\t\t\t\t\t\t\tvalue: 'nodeInputBinary',\n\t\t\t\t\t\t\tdescription: 'Summarize the binary data coming into this node from the previous one',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'Use Document Loader',\n\t\t\t\t\t\t\tvalue: 'documentLoader',\n\t\t\t\t\t\t\tdescription: 'Use a loader sub-node with more configuration options',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Chunking Strategy',\n\t\t\t\t\tname: 'chunkingMode',\n\t\t\t\t\tnoDataExpression: true,\n\t\t\t\t\ttype: 'options',\n\t\t\t\t\tdescription: 'Chunk splitting strategy',\n\t\t\t\t\tdefault: 'simple',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'Simple (Define Below)',\n\t\t\t\t\t\t\tvalue: 'simple',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'Advanced',\n\t\t\t\t\t\t\tvalue: 'advanced',\n\t\t\t\t\t\t\tdescription: 'Use a splitter sub-node with more configuration options',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t'/operationMode': ['nodeInputJson', 'nodeInputBinary'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Characters Per Chunk',\n\t\t\t\t\tname: 'chunkSize',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Controls the max size (in terms of number of characters) of the final document chunk',\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: 1000,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t'/chunkingMode': ['simple'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Chunk Overlap (Characters)',\n\t\t\t\t\tname: 'chunkOverlap',\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdescription: 'Specifies how much characters overlap there should be between chunks',\n\t\t\t\t\tdefault: 200,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t'/chunkingMode': ['simple'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Options',\n\t\t\t\t\tname: 'options',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t\tdefault: {},\n\t\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdisplayName: 'Input Data Field Name',\n\t\t\t\t\t\t\tname: 'binaryDataKey',\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdefault: 'data',\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t'The name of the field in the agent or chain’s input that contains the binary file to be processed',\n\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t\t'/operationMode': ['nodeInputBinary'],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdisplayName: 'Summarization Method and Prompts',\n\t\t\t\t\t\t\tname: 'summarizationMethodAndPrompts',\n\t\t\t\t\t\t\ttype: 'fixedCollection',\n\t\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\t\tvalues: {\n\t\t\t\t\t\t\t\t\tsummarizationMethod: 'map_reduce',\n\t\t\t\t\t\t\t\t\tprompt: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\tcombineMapPrompt: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\t\t\t\ttypeOptions: {},\n\t\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: 'values',\n\t\t\t\t\t\t\t\t\tdisplayName: 'Values',\n\t\t\t\t\t\t\t\t\tvalues: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Summarization Method',\n\t\t\t\t\t\t\t\t\t\t\tname: 'summarizationMethod',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\t\t\t\t\t\tdescription: 'The type of summarization to run',\n\t\t\t\t\t\t\t\t\t\t\tdefault: 'map_reduce',\n\t\t\t\t\t\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: 'Map Reduce (Recommended)',\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: 'map_reduce',\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'Summarize each document (or chunk) individually, then summarize those summaries',\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: 'Refine',\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: 'refine',\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'Summarize the first document (or chunk). Then update that summary based on the next document (or chunk), and repeat.',\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: 'Stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: 'stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'Pass all documents (or chunks) at once. Ideal for small datasets.',\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Individual Summary Prompt',\n\t\t\t\t\t\t\t\t\t\t\tname: 'combineMapPrompt',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\t\thint: 'The prompt to summarize an individual document (or chunk)',\n\t\t\t\t\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t'/options.summarizationMethodAndPrompts.values.summarizationMethod': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'refine',\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tdefault: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\trows: 9,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Final Prompt to Combine',\n\t\t\t\t\t\t\t\t\t\t\tname: 'prompt',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\t\tdefault: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t\thint: 'The prompt to combine individual summaries',\n\t\t\t\t\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t'/options.summarizationMethodAndPrompts.values.summarizationMethod': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'refine',\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\trows: 9,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Prompt',\n\t\t\t\t\t\t\t\t\t\t\tname: 'prompt',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\t\tdefault: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t'/options.summarizationMethodAndPrompts.values.summarizationMethod': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'refine',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'map_reduce',\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\trows: 9,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Subsequent (Refine) Prompt',\n\t\t\t\t\t\t\t\t\t\t\tname: 'refinePrompt',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t'/options.summarizationMethodAndPrompts.values.summarizationMethod': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'map_reduce',\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tdefault: REFINE_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t\thint: 'The prompt to refine the summary based on the next document (or chunk)',\n\t\t\t\t\t\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\trows: 9,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Initial Prompt',\n\t\t\t\t\t\t\t\t\t\t\tname: 'refineQuestionPrompt',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t'/options.summarizationMethodAndPrompts.values.summarizationMethod': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'map_reduce',\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tdefault: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t\thint: 'The prompt for the first document (or chunk)',\n\t\t\t\t\t\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\trows: 9,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tthis.logger.debug('Executing Summarization Chain V2');\n\t\tconst operationMode = this.getNodeParameter('operationMode', 0, 'nodeInputJson') as\n\t\t\t| 'nodeInputJson'\n\t\t\t| 'nodeInputBinary'\n\t\t\t| 'documentLoader';\n\t\tconst chunkingMode = this.getNodeParameter('chunkingMode', 0, 'simple') as\n\t\t\t| 'simple'\n\t\t\t| 'advanced';\n\n\t\tconst items = this.getInputData();\n\t\tconst returnData: INodeExecutionData[] = [];\n\n\t\tfor (let itemIndex = 0; itemIndex < items.length; itemIndex++) {\n\t\t\ttry {\n\t\t\t\tconst model = (await this.getInputConnectionData(\n\t\t\t\t\tNodeConnectionTypes.AiLanguageModel,\n\t\t\t\t\t0,\n\t\t\t\t)) as BaseLanguageModel;\n\n\t\t\t\tconst summarizationMethodAndPrompts = this.getNodeParameter(\n\t\t\t\t\t'options.summarizationMethodAndPrompts.values',\n\t\t\t\t\titemIndex,\n\t\t\t\t\t{},\n\t\t\t\t) as {\n\t\t\t\t\tprompt?: string;\n\t\t\t\t\trefineQuestionPrompt?: string;\n\t\t\t\t\trefinePrompt?: string;\n\t\t\t\t\tsummarizationMethod: 'map_reduce' | 'stuff' | 'refine';\n\t\t\t\t\tcombineMapPrompt?: string;\n\t\t\t\t};\n\n\t\t\t\tconst chainArgs = getChainPromptsArgs(\n\t\t\t\t\tsummarizationMethodAndPrompts.summarizationMethod ?? 'map_reduce',\n\t\t\t\t\tsummarizationMethodAndPrompts,\n\t\t\t\t);\n\n\t\t\t\tconst chain = loadSummarizationChain(model, chainArgs);\n\t\t\t\tconst item = items[itemIndex];\n\n\t\t\t\tlet processedDocuments: Document[];\n\n\t\t\t\t// Use dedicated document loader input to load documents\n\t\t\t\tif (operationMode === 'documentLoader') {\n\t\t\t\t\tconst documentInput = (await this.getInputConnectionData(\n\t\t\t\t\t\tNodeConnectionTypes.AiDocument,\n\t\t\t\t\t\t0,\n\t\t\t\t\t)) as N8nJsonLoader | Array<Document<Record<string, unknown>>>;\n\n\t\t\t\t\tconst isN8nLoader =\n\t\t\t\t\t\tdocumentInput instanceof N8nJsonLoader || documentInput instanceof N8nBinaryLoader;\n\n\t\t\t\t\tprocessedDocuments = isN8nLoader\n\t\t\t\t\t\t? await documentInput.processItem(item, itemIndex)\n\t\t\t\t\t\t: documentInput;\n\n\t\t\t\t\tconst response = await chain.withConfig(getTracingConfig(this)).invoke({\n\t\t\t\t\t\tinput_documents: processedDocuments,\n\t\t\t\t\t});\n\n\t\t\t\t\treturnData.push({ json: { response } });\n\t\t\t\t}\n\n\t\t\t\t// Take the input and use binary or json loader\n\t\t\t\tif (['nodeInputJson', 'nodeInputBinary'].includes(operationMode)) {\n\t\t\t\t\tlet textSplitter: TextSplitter | undefined;\n\n\t\t\t\t\tswitch (chunkingMode) {\n\t\t\t\t\t\t// In simple mode we use recursive character splitter with default settings\n\t\t\t\t\t\tcase 'simple':\n\t\t\t\t\t\t\tconst chunkSize = this.getNodeParameter('chunkSize', itemIndex, 1000) as number;\n\t\t\t\t\t\t\tconst chunkOverlap = this.getNodeParameter('chunkOverlap', itemIndex, 200) as number;\n\n\t\t\t\t\t\t\ttextSplitter = new RecursiveCharacterTextSplitter({ chunkOverlap, chunkSize });\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t// In advanced mode user can connect text splitter node so we just retrieve it\n\t\t\t\t\t\tcase 'advanced':\n\t\t\t\t\t\t\ttextSplitter = (await this.getInputConnectionData(\n\t\t\t\t\t\t\t\tNodeConnectionTypes.AiTextSplitter,\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t)) as TextSplitter | undefined;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet processor: N8nJsonLoader | N8nBinaryLoader;\n\t\t\t\t\tif (operationMode === 'nodeInputBinary') {\n\t\t\t\t\t\tconst binaryDataKey = this.getNodeParameter(\n\t\t\t\t\t\t\t'options.binaryDataKey',\n\t\t\t\t\t\t\titemIndex,\n\t\t\t\t\t\t\t'data',\n\t\t\t\t\t\t) as string;\n\t\t\t\t\t\tprocessor = new N8nBinaryLoader(this, 'options.', binaryDataKey, textSplitter);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprocessor = new N8nJsonLoader(this, 'options.', textSplitter);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst processedItem = await processor.processItem(item, itemIndex);\n\t\t\t\t\tconst response = await chain.invoke(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tinput_documents: processedItem,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ signal: this.getExecutionCancelSignal() },\n\t\t\t\t\t);\n\t\t\t\t\treturnData.push({ json: { response } });\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tif (this.continueOnFail()) {\n\t\t\t\t\treturnData.push({ json: { error: error.message }, pairedItem: { item: itemIndex } });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\treturn [returnData];\n\t}\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../nodes/chains/ChainSummarization/V2/ChainSummarizationV2.node.ts"],"sourcesContent":["import type { Document } from '@langchain/core/documents';\nimport type { BaseLanguageModel } from '@langchain/core/language_models/base';\nimport type { ChainValues } from '@langchain/core/utils/types';\nimport type { TextSplitter } from '@langchain/textsplitters';\nimport { RecursiveCharacterTextSplitter } from '@langchain/textsplitters';\nimport { loadSummarizationChain } from 'langchain/chains';\nimport type {\n\tINodeTypeBaseDescription,\n\tIExecuteFunctions,\n\tINodeExecutionData,\n\tINodeType,\n\tINodeTypeDescription,\n\tIDataObject,\n\tINodeInputConfiguration,\n} from 'n8n-workflow';\nimport { NodeConnectionTypes, sleep } from 'n8n-workflow';\n\nimport { N8nBinaryLoader } from '@utils/N8nBinaryLoader';\nimport { N8nJsonLoader } from '@utils/N8nJsonLoader';\nimport { getTemplateNoticeField } from '@utils/sharedFields';\nimport { getTracingConfig } from '@utils/tracing';\n\nimport { getChainPromptsArgs } from '../helpers';\nimport { REFINE_PROMPT_TEMPLATE, DEFAULT_PROMPT_TEMPLATE } from '../prompt';\n\nfunction getInputs(parameters: IDataObject) {\n\tconst chunkingMode = parameters?.chunkingMode;\n\tconst operationMode = parameters?.operationMode;\n\tconst inputs: INodeInputConfiguration[] = [\n\t\t{ displayName: '', type: 'main' },\n\t\t{\n\t\t\tdisplayName: 'Model',\n\t\t\tmaxConnections: 1,\n\t\t\ttype: 'ai_languageModel',\n\t\t\trequired: true,\n\t\t},\n\t];\n\n\tif (operationMode === 'documentLoader') {\n\t\tinputs.push({\n\t\t\tdisplayName: 'Document',\n\t\t\ttype: 'ai_document',\n\t\t\trequired: true,\n\t\t\tmaxConnections: 1,\n\t\t});\n\t\treturn inputs;\n\t}\n\n\tif (chunkingMode === 'advanced') {\n\t\tinputs.push({\n\t\t\tdisplayName: 'Text Splitter',\n\t\t\ttype: 'ai_textSplitter',\n\t\t\trequired: false,\n\t\t\tmaxConnections: 1,\n\t\t});\n\t\treturn inputs;\n\t}\n\treturn inputs;\n}\n\nexport class ChainSummarizationV2 implements INodeType {\n\tdescription: INodeTypeDescription;\n\n\tconstructor(baseDescription: INodeTypeBaseDescription) {\n\t\tthis.description = {\n\t\t\t...baseDescription,\n\t\t\tversion: [2],\n\t\t\tdefaults: {\n\t\t\t\tname: 'Summarization Chain',\n\t\t\t\tcolor: '#909298',\n\t\t\t},\n\t\t\t// eslint-disable-next-line n8n-nodes-base/node-class-description-inputs-wrong-regular-node\n\t\t\tinputs: `={{ ((parameter) => { ${getInputs.toString()}; return getInputs(parameter) })($parameter) }}`,\n\t\t\toutputs: [NodeConnectionTypes.Main],\n\t\t\tcredentials: [],\n\t\t\tproperties: [\n\t\t\t\tgetTemplateNoticeField(1951),\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Data to Summarize',\n\t\t\t\t\tname: 'operationMode',\n\t\t\t\t\tnoDataExpression: true,\n\t\t\t\t\ttype: 'options',\n\t\t\t\t\tdescription: 'How to pass data into the summarization chain',\n\t\t\t\t\tdefault: 'nodeInputJson',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'Use Node Input (JSON)',\n\t\t\t\t\t\t\tvalue: 'nodeInputJson',\n\t\t\t\t\t\t\tdescription: 'Summarize the JSON data coming into this node from the previous one',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'Use Node Input (Binary)',\n\t\t\t\t\t\t\tvalue: 'nodeInputBinary',\n\t\t\t\t\t\t\tdescription: 'Summarize the binary data coming into this node from the previous one',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'Use Document Loader',\n\t\t\t\t\t\t\tvalue: 'documentLoader',\n\t\t\t\t\t\t\tdescription: 'Use a loader sub-node with more configuration options',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Chunking Strategy',\n\t\t\t\t\tname: 'chunkingMode',\n\t\t\t\t\tnoDataExpression: true,\n\t\t\t\t\ttype: 'options',\n\t\t\t\t\tdescription: 'Chunk splitting strategy',\n\t\t\t\t\tdefault: 'simple',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'Simple (Define Below)',\n\t\t\t\t\t\t\tvalue: 'simple',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: 'Advanced',\n\t\t\t\t\t\t\tvalue: 'advanced',\n\t\t\t\t\t\t\tdescription: 'Use a splitter sub-node with more configuration options',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t'/operationMode': ['nodeInputJson', 'nodeInputBinary'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Characters Per Chunk',\n\t\t\t\t\tname: 'chunkSize',\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Controls the max size (in terms of number of characters) of the final document chunk',\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdefault: 1000,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t'/chunkingMode': ['simple'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Chunk Overlap (Characters)',\n\t\t\t\t\tname: 'chunkOverlap',\n\t\t\t\t\ttype: 'number',\n\t\t\t\t\tdescription: 'Specifies how much characters overlap there should be between chunks',\n\t\t\t\t\tdefault: 200,\n\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t'/chunkingMode': ['simple'],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tdisplayName: 'Options',\n\t\t\t\t\tname: 'options',\n\t\t\t\t\ttype: 'collection',\n\t\t\t\t\tdefault: {},\n\t\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdisplayName: 'Input Data Field Name',\n\t\t\t\t\t\t\tname: 'binaryDataKey',\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdefault: 'data',\n\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t'The name of the field in the agent or chain’s input that contains the binary file to be processed',\n\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\tshow: {\n\t\t\t\t\t\t\t\t\t'/operationMode': ['nodeInputBinary'],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdisplayName: 'Summarization Method and Prompts',\n\t\t\t\t\t\t\tname: 'summarizationMethodAndPrompts',\n\t\t\t\t\t\t\ttype: 'fixedCollection',\n\t\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\t\tvalues: {\n\t\t\t\t\t\t\t\t\tsummarizationMethod: 'map_reduce',\n\t\t\t\t\t\t\t\t\tprompt: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\tcombineMapPrompt: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tplaceholder: 'Add Option',\n\t\t\t\t\t\t\ttypeOptions: {},\n\t\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: 'values',\n\t\t\t\t\t\t\t\t\tdisplayName: 'Values',\n\t\t\t\t\t\t\t\t\tvalues: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Summarization Method',\n\t\t\t\t\t\t\t\t\t\t\tname: 'summarizationMethod',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'options',\n\t\t\t\t\t\t\t\t\t\t\tdescription: 'The type of summarization to run',\n\t\t\t\t\t\t\t\t\t\t\tdefault: 'map_reduce',\n\t\t\t\t\t\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: 'Map Reduce (Recommended)',\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: 'map_reduce',\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'Summarize each document (or chunk) individually, then summarize those summaries',\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: 'Refine',\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: 'refine',\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'Summarize the first document (or chunk). Then update that summary based on the next document (or chunk), and repeat.',\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: 'Stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: 'stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'Pass all documents (or chunks) at once. Ideal for small datasets.',\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Individual Summary Prompt',\n\t\t\t\t\t\t\t\t\t\t\tname: 'combineMapPrompt',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\t\thint: 'The prompt to summarize an individual document (or chunk)',\n\t\t\t\t\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t'/options.summarizationMethodAndPrompts.values.summarizationMethod': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'refine',\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tdefault: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\trows: 9,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Final Prompt to Combine',\n\t\t\t\t\t\t\t\t\t\t\tname: 'prompt',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\t\tdefault: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t\thint: 'The prompt to combine individual summaries',\n\t\t\t\t\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t'/options.summarizationMethodAndPrompts.values.summarizationMethod': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'refine',\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\trows: 9,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Prompt',\n\t\t\t\t\t\t\t\t\t\t\tname: 'prompt',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\t\tdefault: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t'/options.summarizationMethodAndPrompts.values.summarizationMethod': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'refine',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'map_reduce',\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\trows: 9,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Subsequent (Refine) Prompt',\n\t\t\t\t\t\t\t\t\t\t\tname: 'refinePrompt',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t'/options.summarizationMethodAndPrompts.values.summarizationMethod': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'map_reduce',\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tdefault: REFINE_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t\thint: 'The prompt to refine the summary based on the next document (or chunk)',\n\t\t\t\t\t\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\trows: 9,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdisplayName: 'Initial Prompt',\n\t\t\t\t\t\t\t\t\t\t\tname: 'refineQuestionPrompt',\n\t\t\t\t\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\t\t\t\t\tdisplayOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\thide: {\n\t\t\t\t\t\t\t\t\t\t\t\t\t'/options.summarizationMethodAndPrompts.values.summarizationMethod': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'stuff',\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'map_reduce',\n\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tdefault: DEFAULT_PROMPT_TEMPLATE,\n\t\t\t\t\t\t\t\t\t\t\thint: 'The prompt for the first document (or chunk)',\n\t\t\t\t\t\t\t\t\t\t\ttypeOptions: {\n\t\t\t\t\t\t\t\t\t\t\t\trows: 9,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdisplayName: 'Batch Processing',\n\t\t\t\t\t\t\tname: 'batching',\n\t\t\t\t\t\t\ttype: 'collection',\n\t\t\t\t\t\t\tdescription: 'Batch processing options for rate limiting',\n\t\t\t\t\t\t\tdefault: {},\n\t\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdisplayName: 'Batch Size',\n\t\t\t\t\t\t\t\t\tname: 'batchSize',\n\t\t\t\t\t\t\t\t\tdefault: 100,\n\t\t\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t'How many items to process in parallel. This is useful for rate limiting.',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdisplayName: 'Delay Between Batches',\n\t\t\t\t\t\t\t\t\tname: 'delayBetweenBatches',\n\t\t\t\t\t\t\t\t\tdefault: 0,\n\t\t\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t'Delay in milliseconds between batches. This is useful for rate limiting.',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t}\n\n\tasync execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {\n\t\tthis.logger.debug('Executing Summarization Chain V2');\n\t\tconst operationMode = this.getNodeParameter('operationMode', 0, 'nodeInputJson') as\n\t\t\t| 'nodeInputJson'\n\t\t\t| 'nodeInputBinary'\n\t\t\t| 'documentLoader';\n\t\tconst chunkingMode = this.getNodeParameter('chunkingMode', 0, 'simple') as\n\t\t\t| 'simple'\n\t\t\t| 'advanced';\n\n\t\tconst items = this.getInputData();\n\t\tconst returnData: INodeExecutionData[] = [];\n\t\tconst { batchSize, delayBetweenBatches } = this.getNodeParameter('options.batching', 0, {\n\t\t\tbatchSize: 100,\n\t\t\tdelayBetweenBatches: 0,\n\t\t}) as {\n\t\t\tbatchSize: number;\n\t\t\tdelayBetweenBatches: number;\n\t\t};\n\n\t\tfor (let i = 0; i < items.length; i += batchSize) {\n\t\t\tconst batch = items.slice(i, i + batchSize);\n\t\t\tconst batchPromises = batch.map(async (_item, batchIndex) => {\n\t\t\t\tconst itemIndex = i + batchIndex;\n\n\t\t\t\tconst model = (await this.getInputConnectionData(\n\t\t\t\t\tNodeConnectionTypes.AiLanguageModel,\n\t\t\t\t\t0,\n\t\t\t\t)) as BaseLanguageModel;\n\n\t\t\t\tconst summarizationMethodAndPrompts = this.getNodeParameter(\n\t\t\t\t\t'options.summarizationMethodAndPrompts.values',\n\t\t\t\t\titemIndex,\n\t\t\t\t\t{},\n\t\t\t\t) as {\n\t\t\t\t\tprompt?: string;\n\t\t\t\t\trefineQuestionPrompt?: string;\n\t\t\t\t\trefinePrompt?: string;\n\t\t\t\t\tsummarizationMethod: 'map_reduce' | 'stuff' | 'refine';\n\t\t\t\t\tcombineMapPrompt?: string;\n\t\t\t\t};\n\n\t\t\t\tconst chainArgs = getChainPromptsArgs(\n\t\t\t\t\tsummarizationMethodAndPrompts.summarizationMethod ?? 'map_reduce',\n\t\t\t\t\tsummarizationMethodAndPrompts,\n\t\t\t\t);\n\n\t\t\t\tconst chain = loadSummarizationChain(model, chainArgs);\n\t\t\t\tconst item = items[itemIndex];\n\n\t\t\t\tlet processedDocuments: Document[];\n\t\t\t\tlet output: ChainValues = {};\n\n\t\t\t\t// Use dedicated document loader input to load documents\n\t\t\t\tif (operationMode === 'documentLoader') {\n\t\t\t\t\tconst documentInput = (await this.getInputConnectionData(\n\t\t\t\t\t\tNodeConnectionTypes.AiDocument,\n\t\t\t\t\t\t0,\n\t\t\t\t\t)) as N8nJsonLoader | Array<Document<Record<string, unknown>>>;\n\n\t\t\t\t\tconst isN8nLoader =\n\t\t\t\t\t\tdocumentInput instanceof N8nJsonLoader || documentInput instanceof N8nBinaryLoader;\n\n\t\t\t\t\tprocessedDocuments = isN8nLoader\n\t\t\t\t\t\t? await documentInput.processItem(item, itemIndex)\n\t\t\t\t\t\t: documentInput;\n\n\t\t\t\t\toutput = await chain.withConfig(getTracingConfig(this)).invoke({\n\t\t\t\t\t\tinput_documents: processedDocuments,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Take the input and use binary or json loader\n\t\t\t\tif (['nodeInputJson', 'nodeInputBinary'].includes(operationMode)) {\n\t\t\t\t\tlet textSplitter: TextSplitter | undefined;\n\n\t\t\t\t\tswitch (chunkingMode) {\n\t\t\t\t\t\t// In simple mode we use recursive character splitter with default settings\n\t\t\t\t\t\tcase 'simple':\n\t\t\t\t\t\t\tconst chunkSize = this.getNodeParameter('chunkSize', itemIndex, 1000) as number;\n\t\t\t\t\t\t\tconst chunkOverlap = this.getNodeParameter('chunkOverlap', itemIndex, 200) as number;\n\n\t\t\t\t\t\t\ttextSplitter = new RecursiveCharacterTextSplitter({ chunkOverlap, chunkSize });\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t// In advanced mode user can connect text splitter node so we just retrieve it\n\t\t\t\t\t\tcase 'advanced':\n\t\t\t\t\t\t\ttextSplitter = (await this.getInputConnectionData(\n\t\t\t\t\t\t\t\tNodeConnectionTypes.AiTextSplitter,\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t)) as TextSplitter | undefined;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet processor: N8nJsonLoader | N8nBinaryLoader;\n\t\t\t\t\tif (operationMode === 'nodeInputBinary') {\n\t\t\t\t\t\tconst binaryDataKey = this.getNodeParameter(\n\t\t\t\t\t\t\t'options.binaryDataKey',\n\t\t\t\t\t\t\titemIndex,\n\t\t\t\t\t\t\t'data',\n\t\t\t\t\t\t) as string;\n\t\t\t\t\t\tprocessor = new N8nBinaryLoader(this, 'options.', binaryDataKey, textSplitter);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tprocessor = new N8nJsonLoader(this, 'options.', textSplitter);\n\t\t\t\t\t}\n\n\t\t\t\t\tconst processedItem = await processor.processItem(item, itemIndex);\n\t\t\t\t\toutput = await chain.invoke(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tinput_documents: processedItem,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{ signal: this.getExecutionCancelSignal() },\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn output;\n\t\t\t});\n\n\t\t\tconst batchResults = await Promise.allSettled(batchPromises);\n\t\t\tbatchResults.forEach((response, index) => {\n\t\t\t\tif (response.status === 'rejected') {\n\t\t\t\t\tconst error = response.reason as Error;\n\t\t\t\t\tif (this.continueOnFail()) {\n\t\t\t\t\t\treturnData.push({\n\t\t\t\t\t\t\tjson: { error: error.message },\n\t\t\t\t\t\t\tpairedItem: { item: i + index },\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst output = response.value;\n\t\t\t\t\treturnData.push({ json: { output } });\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Add delay between batches if not the last batch\n\t\t\tif (i + batchSize < items.length && delayBetweenBatches > 0) {\n\t\t\t\tawait sleep(delayBetweenBatches);\n\t\t\t}\n\t\t}\n\n\t\treturn [returnData];\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,2BAA+C;AAC/C,oBAAuC;AAUvC,0BAA2C;AAE3C,6BAAgC;AAChC,2BAA8B;AAC9B,0BAAuC;AACvC,qBAAiC;AAEjC,qBAAoC;AACpC,oBAAgE;AAEhE,SAAS,UAAU,YAAyB;AAC3C,QAAM,eAAe,YAAY;AACjC,QAAM,gBAAgB,YAAY;AAClC,QAAM,SAAoC;AAAA,IACzC,EAAE,aAAa,IAAI,MAAM,OAAO;AAAA,IAChC;AAAA,MACC,aAAa;AAAA,MACb,gBAAgB;AAAA,MAChB,MAAM;AAAA,MACN,UAAU;AAAA,IACX;AAAA,EACD;AAEA,MAAI,kBAAkB,kBAAkB;AACvC,WAAO,KAAK;AAAA,MACX,aAAa;AAAA,MACb,MAAM;AAAA,MACN,UAAU;AAAA,MACV,gBAAgB;AAAA,IACjB,CAAC;AACD,WAAO;AAAA,EACR;AAEA,MAAI,iBAAiB,YAAY;AAChC,WAAO,KAAK;AAAA,MACX,aAAa;AAAA,MACb,MAAM;AAAA,MACN,UAAU;AAAA,MACV,gBAAgB;AAAA,IACjB,CAAC;AACD,WAAO;AAAA,EACR;AACA,SAAO;AACR;AAEO,MAAM,qBAA0C;AAAA,EAGtD,YAAY,iBAA2C;AACtD,SAAK,cAAc;AAAA,MAClB,GAAG;AAAA,MACH,SAAS,CAAC,CAAC;AAAA,MACX,UAAU;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,MACR;AAAA;AAAA,MAEA,QAAQ,yBAAyB,UAAU,SAAS,CAAC;AAAA,MACrD,SAAS,CAAC,wCAAoB,IAAI;AAAA,MAClC,aAAa,CAAC;AAAA,MACd,YAAY;AAAA,YACX,4CAAuB,IAAI;AAAA,QAC3B;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,kBAAkB;AAAA,UAClB,MAAM;AAAA,UACN,aAAa;AAAA,UACb,SAAS;AAAA,UACT,SAAS;AAAA,YACR;AAAA,cACC,MAAM;AAAA,cACN,OAAO;AAAA,cACP,aAAa;AAAA,YACd;AAAA,YACA;AAAA,cACC,MAAM;AAAA,cACN,OAAO;AAAA,cACP,aAAa;AAAA,YACd;AAAA,YACA;AAAA,cACC,MAAM;AAAA,cACN,OAAO;AAAA,cACP,aAAa;AAAA,YACd;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,kBAAkB;AAAA,UAClB,MAAM;AAAA,UACN,aAAa;AAAA,UACb,SAAS;AAAA,UACT,SAAS;AAAA,YACR;AAAA,cACC,MAAM;AAAA,cACN,OAAO;AAAA,YACR;AAAA,YACA;AAAA,cACC,MAAM;AAAA,cACN,OAAO;AAAA,cACP,aAAa;AAAA,YACd;AAAA,UACD;AAAA,UACA,gBAAgB;AAAA,YACf,MAAM;AAAA,cACL,kBAAkB,CAAC,iBAAiB,iBAAiB;AAAA,YACtD;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,aACC;AAAA,UACD,MAAM;AAAA,UACN,SAAS;AAAA,UACT,gBAAgB;AAAA,YACf,MAAM;AAAA,cACL,iBAAiB,CAAC,QAAQ;AAAA,YAC3B;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,UACb,SAAS;AAAA,UACT,gBAAgB;AAAA,YACf,MAAM;AAAA,cACL,iBAAiB,CAAC,QAAQ;AAAA,YAC3B;AAAA,UACD;AAAA,QACD;AAAA,QACA;AAAA,UACC,aAAa;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,CAAC;AAAA,UACV,aAAa;AAAA,UACb,SAAS;AAAA,YACR;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,cACT,aACC;AAAA,cACD,gBAAgB;AAAA,gBACf,MAAM;AAAA,kBACL,kBAAkB,CAAC,iBAAiB;AAAA,gBACrC;AAAA,cACD;AAAA,YACD;AAAA,YACA;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,gBACR,QAAQ;AAAA,kBACP,qBAAqB;AAAA,kBACrB,QAAQ;AAAA,kBACR,kBAAkB;AAAA,gBACnB;AAAA,cACD;AAAA,cACA,aAAa;AAAA,cACb,aAAa,CAAC;AAAA,cACd,SAAS;AAAA,gBACR;AAAA,kBACC,MAAM;AAAA,kBACN,aAAa;AAAA,kBACb,QAAQ;AAAA,oBACP;AAAA,sBACC,aAAa;AAAA,sBACb,MAAM;AAAA,sBACN,MAAM;AAAA,sBACN,aAAa;AAAA,sBACb,SAAS;AAAA,sBACT,SAAS;AAAA,wBACR;AAAA,0BACC,MAAM;AAAA,0BACN,OAAO;AAAA,0BACP,aACC;AAAA,wBACF;AAAA,wBACA;AAAA,0BACC,MAAM;AAAA,0BACN,OAAO;AAAA,0BACP,aACC;AAAA,wBACF;AAAA,wBACA;AAAA,0BACC,MAAM;AAAA,0BACN,OAAO;AAAA,0BACP,aACC;AAAA,wBACF;AAAA,sBACD;AAAA,oBACD;AAAA,oBACA;AAAA,sBACC,aAAa;AAAA,sBACb,MAAM;AAAA,sBACN,MAAM;AAAA,sBACN,MAAM;AAAA,sBACN,gBAAgB;AAAA,wBACf,MAAM;AAAA,0BACL,qEAAqE;AAAA,4BACpE;AAAA,4BACA;AAAA,0BACD;AAAA,wBACD;AAAA,sBACD;AAAA,sBACA,SAAS;AAAA,sBACT,aAAa;AAAA,wBACZ,MAAM;AAAA,sBACP;AAAA,oBACD;AAAA,oBACA;AAAA,sBACC,aAAa;AAAA,sBACb,MAAM;AAAA,sBACN,MAAM;AAAA,sBACN,SAAS;AAAA,sBACT,MAAM;AAAA,sBACN,gBAAgB;AAAA,wBACf,MAAM;AAAA,0BACL,qEAAqE;AAAA,4BACpE;AAAA,4BACA;AAAA,0BACD;AAAA,wBACD;AAAA,sBACD;AAAA,sBACA,aAAa;AAAA,wBACZ,MAAM;AAAA,sBACP;AAAA,oBACD;AAAA,oBACA;AAAA,sBACC,aAAa;AAAA,sBACb,MAAM;AAAA,sBACN,MAAM;AAAA,sBACN,SAAS;AAAA,sBACT,gBAAgB;AAAA,wBACf,MAAM;AAAA,0BACL,qEAAqE;AAAA,4BACpE;AAAA,4BACA;AAAA,0BACD;AAAA,wBACD;AAAA,sBACD;AAAA,sBACA,aAAa;AAAA,wBACZ,MAAM;AAAA,sBACP;AAAA,oBACD;AAAA,oBACA;AAAA,sBACC,aAAa;AAAA,sBACb,MAAM;AAAA,sBACN,MAAM;AAAA,sBACN,gBAAgB;AAAA,wBACf,MAAM;AAAA,0BACL,qEAAqE;AAAA,4BACpE;AAAA,4BACA;AAAA,0BACD;AAAA,wBACD;AAAA,sBACD;AAAA,sBACA,SAAS;AAAA,sBACT,MAAM;AAAA,sBACN,aAAa;AAAA,wBACZ,MAAM;AAAA,sBACP;AAAA,oBACD;AAAA,oBACA;AAAA,sBACC,aAAa;AAAA,sBACb,MAAM;AAAA,sBACN,MAAM;AAAA,sBACN,gBAAgB;AAAA,wBACf,MAAM;AAAA,0BACL,qEAAqE;AAAA,4BACpE;AAAA,4BACA;AAAA,0BACD;AAAA,wBACD;AAAA,sBACD;AAAA,sBACA,SAAS;AAAA,sBACT,MAAM;AAAA,sBACN,aAAa;AAAA,wBACZ,MAAM;AAAA,sBACP;AAAA,oBACD;AAAA,kBACD;AAAA,gBACD;AAAA,cACD;AAAA,YACD;AAAA,YACA;AAAA,cACC,aAAa;AAAA,cACb,MAAM;AAAA,cACN,MAAM;AAAA,cACN,aAAa;AAAA,cACb,SAAS,CAAC;AAAA,cACV,SAAS;AAAA,gBACR;AAAA,kBACC,aAAa;AAAA,kBACb,MAAM;AAAA,kBACN,SAAS;AAAA,kBACT,MAAM;AAAA,kBACN,aACC;AAAA,gBACF;AAAA,gBACA;AAAA,kBACC,aAAa;AAAA,kBACb,MAAM;AAAA,kBACN,SAAS;AAAA,kBACT,MAAM;AAAA,kBACN,aACC;AAAA,gBACF;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,UAAkE;AACvE,SAAK,OAAO,MAAM,kCAAkC;AACpD,UAAM,gBAAgB,KAAK,iBAAiB,iBAAiB,GAAG,eAAe;AAI/E,UAAM,eAAe,KAAK,iBAAiB,gBAAgB,GAAG,QAAQ;AAItE,UAAM,QAAQ,KAAK,aAAa;AAChC,UAAM,aAAmC,CAAC;AAC1C,UAAM,EAAE,WAAW,oBAAoB,IAAI,KAAK,iBAAiB,oBAAoB,GAAG;AAAA,MACvF,WAAW;AAAA,MACX,qBAAqB;AAAA,IACtB,CAAC;AAKD,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,WAAW;AACjD,YAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,SAAS;AAC1C,YAAM,gBAAgB,MAAM,IAAI,OAAO,OAAO,eAAe;AAC5D,cAAM,YAAY,IAAI;AAEtB,cAAM,QAAS,MAAM,KAAK;AAAA,UACzB,wCAAoB;AAAA,UACpB;AAAA,QACD;AAEA,cAAM,gCAAgC,KAAK;AAAA,UAC1C;AAAA,UACA;AAAA,UACA,CAAC;AAAA,QACF;AAQA,cAAM,gBAAY;AAAA,UACjB,8BAA8B,uBAAuB;AAAA,UACrD;AAAA,QACD;AAEA,cAAM,YAAQ,sCAAuB,OAAO,SAAS;AACrD,cAAM,OAAO,MAAM,SAAS;AAE5B,YAAI;AACJ,YAAI,SAAsB,CAAC;AAG3B,YAAI,kBAAkB,kBAAkB;AACvC,gBAAM,gBAAiB,MAAM,KAAK;AAAA,YACjC,wCAAoB;AAAA,YACpB;AAAA,UACD;AAEA,gBAAM,cACL,yBAAyB,sCAAiB,yBAAyB;AAEpE,+BAAqB,cAClB,MAAM,cAAc,YAAY,MAAM,SAAS,IAC/C;AAEH,mBAAS,MAAM,MAAM,eAAW,iCAAiB,IAAI,CAAC,EAAE,OAAO;AAAA,YAC9D,iBAAiB;AAAA,UAClB,CAAC;AAAA,QACF;AAGA,YAAI,CAAC,iBAAiB,iBAAiB,EAAE,SAAS,aAAa,GAAG;AACjE,cAAI;AAEJ,kBAAQ,cAAc;AAAA;AAAA,YAErB,KAAK;AACJ,oBAAM,YAAY,KAAK,iBAAiB,aAAa,WAAW,GAAI;AACpE,oBAAM,eAAe,KAAK,iBAAiB,gBAAgB,WAAW,GAAG;AAEzE,6BAAe,IAAI,oDAA+B,EAAE,cAAc,UAAU,CAAC;AAC7E;AAAA;AAAA,YAGD,KAAK;AACJ,6BAAgB,MAAM,KAAK;AAAA,gBAC1B,wCAAoB;AAAA,gBACpB;AAAA,cACD;AACA;AAAA,YACD;AACC;AAAA,UACF;AAEA,cAAI;AACJ,cAAI,kBAAkB,mBAAmB;AACxC,kBAAM,gBAAgB,KAAK;AAAA,cAC1B;AAAA,cACA;AAAA,cACA;AAAA,YACD;AACA,wBAAY,IAAI,uCAAgB,MAAM,YAAY,eAAe,YAAY;AAAA,UAC9E,OAAO;AACN,wBAAY,IAAI,mCAAc,MAAM,YAAY,YAAY;AAAA,UAC7D;AAEA,gBAAM,gBAAgB,MAAM,UAAU,YAAY,MAAM,SAAS;AACjE,mBAAS,MAAM,MAAM;AAAA,YACpB;AAAA,cACC,iBAAiB;AAAA,YAClB;AAAA,YACA,EAAE,QAAQ,KAAK,yBAAyB,EAAE;AAAA,UAC3C;AAAA,QACD;AACA,eAAO;AAAA,MACR,CAAC;AAED,YAAM,eAAe,MAAM,QAAQ,WAAW,aAAa;AAC3D,mBAAa,QAAQ,CAAC,UAAU,UAAU;AACzC,YAAI,SAAS,WAAW,YAAY;AACnC,gBAAM,QAAQ,SAAS;AACvB,cAAI,KAAK,eAAe,GAAG;AAC1B,uBAAW,KAAK;AAAA,cACf,MAAM,EAAE,OAAO,MAAM,QAAQ;AAAA,cAC7B,YAAY,EAAE,MAAM,IAAI,MAAM;AAAA,YAC/B,CAAC;AAAA,UACF,OAAO;AACN,kBAAM;AAAA,UACP;AAAA,QACD,OAAO;AACN,gBAAM,SAAS,SAAS;AACxB,qBAAW,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAAA,QACrC;AAAA,MACD,CAAC;AAGD,UAAI,IAAI,YAAY,MAAM,UAAU,sBAAsB,GAAG;AAC5D,kBAAM,2BAAM,mBAAmB;AAAA,MAChC;AAAA,IACD;AAEA,WAAO,CAAC,UAAU;AAAA,EACnB;AACD;","names":[]}
@@ -219,6 +219,29 @@ class InformationExtractor {
219
219
  typeOptions: {
220
220
  rows: 6
221
221
  }
222
+ },
223
+ {
224
+ displayName: "Batch Processing",
225
+ name: "batching",
226
+ type: "collection",
227
+ description: "Batch processing options for rate limiting",
228
+ default: {},
229
+ options: [
230
+ {
231
+ displayName: "Batch Size",
232
+ name: "batchSize",
233
+ default: 100,
234
+ type: "number",
235
+ description: "How many items to process in parallel. This is useful for rate limiting, but will impact the agents log output."
236
+ },
237
+ {
238
+ displayName: "Delay Between Batches",
239
+ name: "delayBetweenBatches",
240
+ default: 0,
241
+ type: "number",
242
+ description: "Delay in milliseconds between batches. This is useful for rate limiting."
243
+ }
244
+ ]
222
245
  }
223
246
  ]
224
247
  }
@@ -227,6 +250,10 @@ class InformationExtractor {
227
250
  }
228
251
  async execute() {
229
252
  const items = this.getInputData();
253
+ const { batchSize, delayBetweenBatches } = this.getNodeParameter("options.batching", 0, {
254
+ batchSize: 100,
255
+ delayBetweenBatches: 0
256
+ });
230
257
  const llm = await this.getInputConnectionData(
231
258
  import_n8n_workflow.NodeConnectionTypes.AiLanguageModel,
232
259
  0
@@ -259,31 +286,46 @@ class InformationExtractor {
259
286
  parser = import_output_parsers.OutputFixingParser.fromLLM(llm, import_output_parsers.StructuredOutputParser.fromZodSchema(zodSchema));
260
287
  }
261
288
  const resultData = [];
262
- for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
263
- const input = this.getNodeParameter("text", itemIndex);
264
- const inputPrompt = new import_messages.HumanMessage(input);
265
- const options = this.getNodeParameter("options", itemIndex, {});
266
- const systemPromptTemplate = import_prompts.SystemMessagePromptTemplate.fromTemplate(
267
- `${options.systemPromptTemplate ?? SYSTEM_PROMPT_TEMPLATE}
268
- {format_instructions}`
269
- );
270
- const messages = [
271
- await systemPromptTemplate.format({
272
- format_instructions: parser.getFormatInstructions()
273
- }),
274
- inputPrompt
275
- ];
276
- const prompt = import_prompts.ChatPromptTemplate.fromMessages(messages);
277
- const chain = prompt.pipe(llm).pipe(parser).withConfig((0, import_tracing.getTracingConfig)(this));
278
- try {
279
- const output = await chain.invoke(messages);
280
- resultData.push({ json: { output } });
281
- } catch (error) {
282
- if (this.continueOnFail()) {
283
- resultData.push({ json: { error: error.message }, pairedItem: { item: itemIndex } });
284
- continue;
289
+ for (let i = 0; i < items.length; i += batchSize) {
290
+ const batch = items.slice(i, i + batchSize);
291
+ const batchPromises = batch.map(async (_item, batchItemIndex) => {
292
+ const itemIndex = i + batchItemIndex;
293
+ const input = this.getNodeParameter("text", itemIndex);
294
+ const inputPrompt = new import_messages.HumanMessage(input);
295
+ const options = this.getNodeParameter("options", itemIndex, {});
296
+ const systemPromptTemplate = import_prompts.SystemMessagePromptTemplate.fromTemplate(
297
+ `${options.systemPromptTemplate ?? SYSTEM_PROMPT_TEMPLATE}
298
+ {format_instructions}`
299
+ );
300
+ const messages = [
301
+ await systemPromptTemplate.format({
302
+ format_instructions: parser.getFormatInstructions()
303
+ }),
304
+ inputPrompt
305
+ ];
306
+ const prompt = import_prompts.ChatPromptTemplate.fromMessages(messages);
307
+ const chain = prompt.pipe(llm).pipe(parser).withConfig((0, import_tracing.getTracingConfig)(this));
308
+ return await chain.invoke(messages);
309
+ });
310
+ const batchResults = await Promise.allSettled(batchPromises);
311
+ batchResults.forEach((response, index) => {
312
+ if (response.status === "rejected") {
313
+ const error = response.reason;
314
+ if (this.continueOnFail()) {
315
+ resultData.push({
316
+ json: { error: response.reason },
317
+ pairedItem: { item: i + index }
318
+ });
319
+ return;
320
+ } else {
321
+ throw new import_n8n_workflow.NodeOperationError(this.getNode(), error.message);
322
+ }
285
323
  }
286
- throw error;
324
+ const output = response.value;
325
+ resultData.push({ json: { output } });
326
+ });
327
+ if (i + batchSize < items.length && delayBetweenBatches > 0) {
328
+ await (0, import_n8n_workflow.sleep)(delayBetweenBatches);
287
329
  }
288
330
  }
289
331
  return [resultData];