From 335f363ca16814d6ca1a8a92fc9da145b8eed990 Mon Sep 17 00:00:00 2001 From: Michael Kret <88898367+michael-radency@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:16:02 +0200 Subject: [PATCH] feat: Telemetry include basic llm optional promps, trigger on save workflow event (#8981) --- packages/cli/src/InternalHooks.ts | 43 +++++++++++++---------- packages/workflow/src/Constants.ts | 1 + packages/workflow/src/TelemetryHelpers.ts | 16 ++++++--- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/packages/cli/src/InternalHooks.ts b/packages/cli/src/InternalHooks.ts index 6c5b15dcdc..a18dd7e671 100644 --- a/packages/cli/src/InternalHooks.ts +++ b/packages/cli/src/InternalHooks.ts @@ -202,7 +202,11 @@ export class InternalHooks { } async onWorkflowSaved(user: User, workflow: IWorkflowDb, publicApi: boolean): Promise { - const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes); + const isCloudDeployment = config.getEnv('deployment.type') === 'cloud'; + + const { nodeGraph } = TelemetryHelpers.generateNodesGraph(workflow, this.nodeTypes, { + isCloudDeployment, + }); const notesCount = Object.keys(nodeGraph.notes).length; const overlappingCount = Object.values(nodeGraph.notes).filter( @@ -483,23 +487,26 @@ export class InternalHooks { workflowName: workflow.name, metaData: runData?.data?.resultData?.metadata, }; - promises.push( - telemetryProperties.success - ? this.eventBus.sendWorkflowEvent({ - eventName: 'n8n.workflow.success', - payload: sharedEventPayload, - }) - : this.eventBus.sendWorkflowEvent({ - eventName: 'n8n.workflow.failed', - payload: { - ...sharedEventPayload, - lastNodeExecuted: runData?.data.resultData.lastNodeExecuted, - errorNodeType: telemetryProperties.error_node_type, - errorNodeId: telemetryProperties.error_node_id?.toString(), - errorMessage: telemetryProperties.error_message?.toString(), - }, - }), - ); + let event; + if (telemetryProperties.success) { + event = this.eventBus.sendWorkflowEvent({ + eventName: 'n8n.workflow.success', + payload: sharedEventPayload, + }); + } else { + event = this.eventBus.sendWorkflowEvent({ + eventName: 'n8n.workflow.failed', + payload: { + ...sharedEventPayload, + lastNodeExecuted: runData?.data.resultData.lastNodeExecuted, + errorNodeType: telemetryProperties.error_node_type, + errorNodeId: telemetryProperties.error_node_id?.toString(), + errorMessage: telemetryProperties.error_message?.toString(), + }, + }); + } + + promises.push(event); void Promise.all([...promises, this.telemetry.trackWorkflowExecution(telemetryProperties)]); } diff --git a/packages/workflow/src/Constants.ts b/packages/workflow/src/Constants.ts index 4ab3e315a0..c4e7b9c197 100644 --- a/packages/workflow/src/Constants.ts +++ b/packages/workflow/src/Constants.ts @@ -52,6 +52,7 @@ export const NODES_WITH_RENAMABLE_CONTENT = new Set([ //@n8n/n8n-nodes-langchain export const MANUAL_CHAT_TRIGGER_LANGCHAIN_NODE_TYPE = '@n8n/n8n-nodes-langchain.manualChatTrigger'; export const AGENT_LANGCHAIN_NODE_TYPE = '@n8n/n8n-nodes-langchain.agent'; +export const CHAIN_LLM_LANGCHAIN_NODE_TYPE = '@n8n/n8n-nodes-langchain.chainLlm'; export const OPENAI_LANGCHAIN_NODE_TYPE = '@n8n/n8n-nodes-langchain.openAi'; export const CHAIN_SUMMARIZATION_LANGCHAIN_NODE_TYPE = '@n8n/n8n-nodes-langchain.chainSummarization'; diff --git a/packages/workflow/src/TelemetryHelpers.ts b/packages/workflow/src/TelemetryHelpers.ts index 5368d94ae8..dc2a6c5847 100644 --- a/packages/workflow/src/TelemetryHelpers.ts +++ b/packages/workflow/src/TelemetryHelpers.ts @@ -13,6 +13,7 @@ import type { import { ApplicationError } from './errors/application.error'; import { AGENT_LANGCHAIN_NODE_TYPE, + CHAIN_LLM_LANGCHAIN_NODE_TYPE, CHAIN_SUMMARIZATION_LANGCHAIN_NODE_TYPE, HTTP_REQUEST_NODE_TYPE, LANGCHAIN_CUSTOM_TOOLS, @@ -168,7 +169,7 @@ export function generateNodesGraph( } if (node.type === AGENT_LANGCHAIN_NODE_TYPE) { - nodeItem.agent = (node.parameters.agent as string) || 'conversationalAgent'; + nodeItem.agent = (node.parameters.agent as string) ?? 'conversationalAgent'; } else if (node.type === HTTP_REQUEST_NODE_TYPE && node.typeVersion === 1) { try { nodeItem.domain = new URL(node.parameters.url as string).hostname; @@ -228,7 +229,7 @@ export function generateNodesGraph( if (options?.isCloudDeployment === true) { if (node.type === OPENAI_LANGCHAIN_NODE_TYPE) { nodeItem.prompts = - (((node.parameters?.messages as IDataObject) || {}).values as IDataObject[]) || []; + (((node.parameters?.messages as IDataObject) ?? {}).values as IDataObject[]) ?? []; } if (node.type === AGENT_LANGCHAIN_NODE_TYPE) { @@ -265,16 +266,21 @@ export function generateNodesGraph( if (node.type === CHAIN_SUMMARIZATION_LANGCHAIN_NODE_TYPE) { nodeItem.prompts = ( - (((node.parameters?.options as IDataObject) || {}) - .summarizationMethodAndPrompts as IDataObject) || {} + (((node.parameters?.options as IDataObject) ?? {}) + .summarizationMethodAndPrompts as IDataObject) ?? {} ).values as IDataObject; } if (LANGCHAIN_CUSTOM_TOOLS.includes(node.type)) { nodeItem.prompts = { - description: (node.parameters?.description as string) || '', + description: (node.parameters?.description as string) ?? '', }; } + + if (node.type === CHAIN_LLM_LANGCHAIN_NODE_TYPE) { + nodeItem.prompts = + (((node.parameters?.messages as IDataObject) ?? {}).messageValues as IDataObject[]) ?? []; + } } nodeGraph.nodes[index.toString()] = nodeItem;