mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
fix(AI Agent Node): Allow removal of system message (#14407)
This commit is contained in:
@@ -263,7 +263,7 @@ export class Agent implements INodeType {
|
||||
icon: 'fa:robot',
|
||||
iconColor: 'black',
|
||||
group: ['transform'],
|
||||
version: [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8],
|
||||
version: [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9],
|
||||
description: 'Generates an action plan and executes it. Can use external tools.',
|
||||
subtitle:
|
||||
"={{ { toolsAgent: 'Tools Agent', conversationalAgent: 'Conversational Agent', openAiFunctionsAgent: 'OpenAI Functions Agent', reActAgent: 'ReAct Agent', sqlAgent: 'SQL Agent', planAndExecuteAgent: 'Plan and Execute Agent' }[$parameter.agent] }}",
|
||||
|
||||
@@ -346,11 +346,20 @@ export async function prepareMessages(
|
||||
outputParser?: N8nOutputParser;
|
||||
},
|
||||
): Promise<BaseMessagePromptTemplateLike[]> {
|
||||
const messages: BaseMessagePromptTemplateLike[] = [
|
||||
['system', `{system_message}${options.outputParser ? '\n\n{formatting_instructions}' : ''}`],
|
||||
['placeholder', '{chat_history}'],
|
||||
['human', '{input}'],
|
||||
];
|
||||
const useSystemMessage = options.systemMessage ?? ctx.getNode().typeVersion < 1.9;
|
||||
|
||||
const messages: BaseMessagePromptTemplateLike[] = [];
|
||||
|
||||
if (useSystemMessage) {
|
||||
messages.push([
|
||||
'system',
|
||||
`{system_message}${options.outputParser ? '\n\n{formatting_instructions}' : ''}`,
|
||||
]);
|
||||
} else if (options.outputParser) {
|
||||
messages.push(['system', '{formatting_instructions}']);
|
||||
}
|
||||
|
||||
messages.push(['placeholder', '{chat_history}'], ['human', '{input}']);
|
||||
|
||||
// If there is binary data and the node option permits it, add a binary message
|
||||
const hasBinaryData = ctx.getInputData()?.[itemIndex]?.binary !== undefined;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Buffer } from 'buffer';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import type { ToolsAgentAction } from 'langchain/dist/agents/tool_calling/output_parser';
|
||||
import type { Tool } from 'langchain/tools';
|
||||
import type { IExecuteFunctions } from 'n8n-workflow';
|
||||
import type { IExecuteFunctions, INode } from 'n8n-workflow';
|
||||
import { NodeOperationError, BINARY_ENCODING, NodeConnectionTypes } from 'n8n-workflow';
|
||||
import type { ZodType } from 'zod';
|
||||
import { z } from 'zod';
|
||||
@@ -232,6 +232,75 @@ describe('prepareMessages', () => {
|
||||
const hasHumanMessage = messages.some((m) => m instanceof HumanMessage);
|
||||
expect(hasHumanMessage).toBe(false);
|
||||
});
|
||||
|
||||
it('should not include system_message in prompt templates if not provided after version 1.9', async () => {
|
||||
const fakeItem = { json: {} };
|
||||
const mockNode = mock<INode>();
|
||||
mockNode.typeVersion = 1.9;
|
||||
mockContext.getInputData.mockReturnValue([fakeItem]);
|
||||
mockContext.getNode.mockReturnValue(mockNode);
|
||||
const messages = await prepareMessages(mockContext, 0, {});
|
||||
|
||||
expect(messages.length).toBe(3);
|
||||
expect(messages).not.toContainEqual(['system', '{system_message}']);
|
||||
});
|
||||
|
||||
it('should include system_message in prompt templates if provided after version 1.9', async () => {
|
||||
const fakeItem = { json: {} };
|
||||
const mockNode = mock<INode>();
|
||||
mockNode.typeVersion = 1.9;
|
||||
mockContext.getInputData.mockReturnValue([fakeItem]);
|
||||
mockContext.getNode.mockReturnValue(mockNode);
|
||||
|
||||
const messages = await prepareMessages(mockContext, 0, { systemMessage: 'Hello' });
|
||||
|
||||
expect(messages.length).toBe(4);
|
||||
expect(messages).toContainEqual(['system', '{system_message}']);
|
||||
});
|
||||
|
||||
it('should include system_message in prompt templates if not provided before version 1.9', async () => {
|
||||
const fakeItem = { json: {} };
|
||||
const mockNode = mock<INode>();
|
||||
mockNode.typeVersion = 1.8;
|
||||
mockContext.getInputData.mockReturnValue([fakeItem]);
|
||||
mockContext.getNode.mockReturnValue(mockNode);
|
||||
|
||||
const messages = await prepareMessages(mockContext, 0, {});
|
||||
|
||||
expect(messages.length).toBe(4);
|
||||
expect(messages).toContainEqual(['system', '{system_message}']);
|
||||
});
|
||||
|
||||
it('should include system_message with formatting_instructions in prompt templates if provided before version 1.9', async () => {
|
||||
const fakeItem = { json: {} };
|
||||
const mockNode = mock<INode>();
|
||||
mockNode.typeVersion = 1.8;
|
||||
mockContext.getInputData.mockReturnValue([fakeItem]);
|
||||
mockContext.getNode.mockReturnValue(mockNode);
|
||||
|
||||
const messages = await prepareMessages(mockContext, 0, {
|
||||
systemMessage: 'Hello',
|
||||
outputParser: mock<N8nOutputParser>(),
|
||||
});
|
||||
|
||||
expect(messages.length).toBe(4);
|
||||
expect(messages).toContainEqual(['system', '{system_message}\n\n{formatting_instructions}']);
|
||||
});
|
||||
|
||||
it('should add formatting instructions when omitting system message after version 1.9', async () => {
|
||||
const fakeItem = { json: {} };
|
||||
const mockNode = mock<INode>();
|
||||
mockNode.typeVersion = 1.9;
|
||||
mockContext.getInputData.mockReturnValue([fakeItem]);
|
||||
mockContext.getNode.mockReturnValue(mockNode);
|
||||
|
||||
const messages = await prepareMessages(mockContext, 0, {
|
||||
outputParser: mock<N8nOutputParser>(),
|
||||
});
|
||||
|
||||
expect(messages.length).toBe(4);
|
||||
expect(messages).toContainEqual(['system', '{formatting_instructions}']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('preparePrompt', () => {
|
||||
|
||||
Reference in New Issue
Block a user