mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
refactor(Basic LLM Chain Node): Refactor Basic LLM Chain & add tests (#13850)
This commit is contained in:
@@ -65,9 +65,11 @@ function getInputs(
|
||||
type,
|
||||
displayName,
|
||||
required: isModelType,
|
||||
maxConnections: [NodeConnectionType.AiLanguageModel, NodeConnectionType.AiMemory].includes(
|
||||
type as NodeConnectionType,
|
||||
)
|
||||
maxConnections: [
|
||||
NodeConnectionType.AiLanguageModel,
|
||||
NodeConnectionType.AiMemory,
|
||||
NodeConnectionType.AiOutputParser,
|
||||
].includes(type as NodeConnectionType)
|
||||
? 1
|
||||
: undefined,
|
||||
};
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import type { BaseChatMemory } from '@langchain/community/memory/chat_memory';
|
||||
import type { BaseOutputParser } from '@langchain/core/output_parsers';
|
||||
import { PromptTemplate } from '@langchain/core/prompts';
|
||||
import { initializeAgentExecutorWithOptions } from 'langchain/agents';
|
||||
import { CombiningOutputParser } from 'langchain/output_parsers';
|
||||
import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
|
||||
import { NodeConnectionType, NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import { isChatInstance, getPromptInputByType, getConnectedTools } from '@utils/helpers';
|
||||
import { getOptionalOutputParsers } from '@utils/output_parsers/N8nOutputParser';
|
||||
import { getOptionalOutputParser } from '@utils/output_parsers/N8nOutputParser';
|
||||
import { throwIfToolSchema } from '@utils/schemaParsing';
|
||||
import { getTracingConfig } from '@utils/tracing';
|
||||
|
||||
@@ -29,7 +27,7 @@ export async function conversationalAgentExecute(
|
||||
| undefined;
|
||||
|
||||
const tools = await getConnectedTools(this, nodeVersion >= 1.5, true, true);
|
||||
const outputParsers = await getOptionalOutputParsers(this);
|
||||
const outputParser = await getOptionalOutputParser(this);
|
||||
|
||||
await checkForStructuredTools(tools, this.getNode(), 'Conversational Agent');
|
||||
|
||||
@@ -58,24 +56,15 @@ export async function conversationalAgentExecute(
|
||||
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
let outputParser: BaseOutputParser | undefined;
|
||||
let prompt: PromptTemplate | undefined;
|
||||
if (outputParsers.length) {
|
||||
if (outputParsers.length === 1) {
|
||||
outputParser = outputParsers[0];
|
||||
} else {
|
||||
outputParser = new CombiningOutputParser(...outputParsers);
|
||||
}
|
||||
if (outputParser) {
|
||||
const formatInstructions = outputParser.getFormatInstructions();
|
||||
|
||||
if (outputParser) {
|
||||
const formatInstructions = outputParser.getFormatInstructions();
|
||||
|
||||
prompt = new PromptTemplate({
|
||||
template: '{input}\n{formatInstructions}',
|
||||
inputVariables: ['input'],
|
||||
partialVariables: { formatInstructions },
|
||||
});
|
||||
}
|
||||
prompt = new PromptTemplate({
|
||||
template: '{input}\n{formatInstructions}',
|
||||
inputVariables: ['input'],
|
||||
partialVariables: { formatInstructions },
|
||||
});
|
||||
}
|
||||
|
||||
const items = this.getInputData();
|
||||
@@ -104,7 +93,7 @@ export async function conversationalAgentExecute(
|
||||
|
||||
const response = await agentExecutor
|
||||
.withConfig(getTracingConfig(this))
|
||||
.invoke({ input, outputParsers });
|
||||
.invoke({ input, outputParser });
|
||||
|
||||
if (outputParser) {
|
||||
response.output = await extractParsedOutput(this, outputParser, response.output as string);
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { BaseOutputParser } from '@langchain/core/output_parsers';
|
||||
import { PromptTemplate } from '@langchain/core/prompts';
|
||||
import { ChatOpenAI } from '@langchain/openai';
|
||||
import type { AgentExecutorInput } from 'langchain/agents';
|
||||
import { AgentExecutor, OpenAIAgent } from 'langchain/agents';
|
||||
import { BufferMemory, type BaseChatMemory } from 'langchain/memory';
|
||||
import { CombiningOutputParser } from 'langchain/output_parsers';
|
||||
import {
|
||||
type IExecuteFunctions,
|
||||
type INodeExecutionData,
|
||||
@@ -13,7 +11,7 @@ import {
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { getConnectedTools, getPromptInputByType } from '@utils/helpers';
|
||||
import { getOptionalOutputParsers } from '@utils/output_parsers/N8nOutputParser';
|
||||
import { getOptionalOutputParser } from '@utils/output_parsers/N8nOutputParser';
|
||||
import { getTracingConfig } from '@utils/tracing';
|
||||
|
||||
import { extractParsedOutput } from '../utils';
|
||||
@@ -38,7 +36,7 @@ export async function openAiFunctionsAgentExecute(
|
||||
| BaseChatMemory
|
||||
| undefined;
|
||||
const tools = await getConnectedTools(this, nodeVersion >= 1.5, false);
|
||||
const outputParsers = await getOptionalOutputParsers(this);
|
||||
const outputParser = await getOptionalOutputParser(this);
|
||||
const options = this.getNodeParameter('options', 0, {}) as {
|
||||
systemMessage?: string;
|
||||
maxIterations?: number;
|
||||
@@ -67,12 +65,8 @@ export async function openAiFunctionsAgentExecute(
|
||||
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
let outputParser: BaseOutputParser | undefined;
|
||||
let prompt: PromptTemplate | undefined;
|
||||
if (outputParsers.length) {
|
||||
outputParser =
|
||||
outputParsers.length === 1 ? outputParsers[0] : new CombiningOutputParser(...outputParsers);
|
||||
|
||||
if (outputParser) {
|
||||
const formatInstructions = outputParser.getFormatInstructions();
|
||||
|
||||
prompt = new PromptTemplate({
|
||||
@@ -107,7 +101,7 @@ export async function openAiFunctionsAgentExecute(
|
||||
|
||||
const response = await agentExecutor
|
||||
.withConfig(getTracingConfig(this))
|
||||
.invoke({ input, outputParsers });
|
||||
.invoke({ input, outputParser });
|
||||
|
||||
if (outputParser) {
|
||||
response.output = await extractParsedOutput(this, outputParser, response.output as string);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
||||
import type { BaseOutputParser } from '@langchain/core/output_parsers';
|
||||
import { PromptTemplate } from '@langchain/core/prompts';
|
||||
import { PlanAndExecuteAgentExecutor } from 'langchain/experimental/plan_and_execute';
|
||||
import { CombiningOutputParser } from 'langchain/output_parsers';
|
||||
import {
|
||||
type IExecuteFunctions,
|
||||
type INodeExecutionData,
|
||||
@@ -11,7 +9,7 @@ import {
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { getConnectedTools, getPromptInputByType } from '@utils/helpers';
|
||||
import { getOptionalOutputParsers } from '@utils/output_parsers/N8nOutputParser';
|
||||
import { getOptionalOutputParser } from '@utils/output_parsers/N8nOutputParser';
|
||||
import { throwIfToolSchema } from '@utils/schemaParsing';
|
||||
import { getTracingConfig } from '@utils/tracing';
|
||||
|
||||
@@ -30,7 +28,7 @@ export async function planAndExecuteAgentExecute(
|
||||
const tools = await getConnectedTools(this, nodeVersion >= 1.5, true, true);
|
||||
|
||||
await checkForStructuredTools(tools, this.getNode(), 'Plan & Execute Agent');
|
||||
const outputParsers = await getOptionalOutputParsers(this);
|
||||
const outputParser = await getOptionalOutputParser(this);
|
||||
|
||||
const options = this.getNodeParameter('options', 0, {}) as {
|
||||
humanMessageTemplate?: string;
|
||||
@@ -44,12 +42,8 @@ export async function planAndExecuteAgentExecute(
|
||||
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
let outputParser: BaseOutputParser | undefined;
|
||||
let prompt: PromptTemplate | undefined;
|
||||
if (outputParsers.length) {
|
||||
outputParser =
|
||||
outputParsers.length === 1 ? outputParsers[0] : new CombiningOutputParser(...outputParsers);
|
||||
|
||||
if (outputParser) {
|
||||
const formatInstructions = outputParser.getFormatInstructions();
|
||||
|
||||
prompt = new PromptTemplate({
|
||||
@@ -84,7 +78,7 @@ export async function planAndExecuteAgentExecute(
|
||||
|
||||
const response = await agentExecutor
|
||||
.withConfig(getTracingConfig(this))
|
||||
.invoke({ input, outputParsers });
|
||||
.invoke({ input, outputParser });
|
||||
|
||||
if (outputParser) {
|
||||
response.output = await extractParsedOutput(this, outputParser, response.output as string);
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import type { BaseLanguageModel } from '@langchain/core/language_models/base';
|
||||
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
||||
import type { BaseOutputParser } from '@langchain/core/output_parsers';
|
||||
import { PromptTemplate } from '@langchain/core/prompts';
|
||||
import { AgentExecutor, ChatAgent, ZeroShotAgent } from 'langchain/agents';
|
||||
import { CombiningOutputParser } from 'langchain/output_parsers';
|
||||
import {
|
||||
type IExecuteFunctions,
|
||||
type INodeExecutionData,
|
||||
@@ -12,7 +10,7 @@ import {
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { getConnectedTools, getPromptInputByType, isChatInstance } from '@utils/helpers';
|
||||
import { getOptionalOutputParsers } from '@utils/output_parsers/N8nOutputParser';
|
||||
import { getOptionalOutputParser } from '@utils/output_parsers/N8nOutputParser';
|
||||
import { throwIfToolSchema } from '@utils/schemaParsing';
|
||||
import { getTracingConfig } from '@utils/tracing';
|
||||
|
||||
@@ -32,7 +30,7 @@ export async function reActAgentAgentExecute(
|
||||
|
||||
await checkForStructuredTools(tools, this.getNode(), 'ReAct Agent');
|
||||
|
||||
const outputParsers = await getOptionalOutputParsers(this);
|
||||
const outputParser = await getOptionalOutputParser(this);
|
||||
|
||||
const options = this.getNodeParameter('options', 0, {}) as {
|
||||
prefix?: string;
|
||||
@@ -66,12 +64,8 @@ export async function reActAgentAgentExecute(
|
||||
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
|
||||
let outputParser: BaseOutputParser | undefined;
|
||||
let prompt: PromptTemplate | undefined;
|
||||
if (outputParsers.length) {
|
||||
outputParser =
|
||||
outputParsers.length === 1 ? outputParsers[0] : new CombiningOutputParser(...outputParsers);
|
||||
|
||||
if (outputParser) {
|
||||
const formatInstructions = outputParser.getFormatInstructions();
|
||||
|
||||
prompt = new PromptTemplate({
|
||||
@@ -107,7 +101,7 @@ export async function reActAgentAgentExecute(
|
||||
|
||||
const response = await agentExecutor
|
||||
.withConfig(getTracingConfig(this))
|
||||
.invoke({ input, outputParsers });
|
||||
.invoke({ input, outputParser });
|
||||
|
||||
if (outputParser) {
|
||||
response.output = await extractParsedOutput(this, outputParser, response.output as string);
|
||||
|
||||
@@ -18,7 +18,7 @@ import { z } from 'zod';
|
||||
|
||||
import { isChatInstance, getPromptInputByType, getConnectedTools } from '@utils/helpers';
|
||||
import {
|
||||
getOptionalOutputParsers,
|
||||
getOptionalOutputParser,
|
||||
type N8nOutputParser,
|
||||
} from '@utils/output_parsers/N8nOutputParser';
|
||||
|
||||
@@ -392,8 +392,7 @@ export async function toolsAgentExecute(this: IExecuteFunctions): Promise<INodeE
|
||||
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const items = this.getInputData();
|
||||
const outputParsers = await getOptionalOutputParsers(this);
|
||||
const outputParser = outputParsers?.[0];
|
||||
const outputParser = await getOptionalOutputParser(this);
|
||||
const tools = await getTools(this, outputParser);
|
||||
|
||||
for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
|
||||
|
||||
Reference in New Issue
Block a user