refactor(Google Gemini Chat Model Node): Provide custom message mapper to N8nLlmTracing (no-changelog) (#13076)

This commit is contained in:
oleg 2025-02-06 17:28:13 +01:00 committed by GitHub
parent 76e0c99613
commit 577d5a1bff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 8 deletions

View file

@ -1,12 +1,13 @@
/* eslint-disable n8n-nodes-base/node-dirname-against-convention */ /* eslint-disable n8n-nodes-base/node-dirname-against-convention */
import type { SafetySetting } from '@google/generative-ai'; import type { SafetySetting } from '@google/generative-ai';
import { ChatGoogleGenerativeAI } from '@langchain/google-genai'; import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
import { import { NodeConnectionType } from 'n8n-workflow';
NodeConnectionType, import type {
type INodeType, NodeError,
type INodeTypeDescription, INodeType,
type ISupplyDataFunctions, INodeTypeDescription,
type SupplyData, ISupplyDataFunctions,
SupplyData,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { getConnectionHintNoticeField } from '@utils/sharedFields'; import { getConnectionHintNoticeField } from '@utils/sharedFields';
@ -15,6 +16,13 @@ import { additionalOptions } from '../gemini-common/additional-options';
import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler'; import { makeN8nLlmFailedAttemptHandler } from '../n8nLlmFailedAttemptHandler';
import { N8nLlmTracing } from '../N8nLlmTracing'; import { N8nLlmTracing } from '../N8nLlmTracing';
function errorDescriptionMapper(error: NodeError) {
if (error.description?.includes('properties: should be non-empty for OBJECT type')) {
return 'Google Gemini requires at least one <a href="https://docs.n8n.io/advanced-ai/examples/using-the-fromai-function/" target="_blank">dynamic parameter</a> when using tools';
}
return error.description ?? 'Unknown error';
}
export class LmChatGoogleGemini implements INodeType { export class LmChatGoogleGemini implements INodeType {
description: INodeTypeDescription = { description: INodeTypeDescription = {
displayName: 'Google Gemini Chat Model', displayName: 'Google Gemini Chat Model',
@ -147,7 +155,7 @@ export class LmChatGoogleGemini implements INodeType {
temperature: options.temperature, temperature: options.temperature,
maxOutputTokens: options.maxOutputTokens, maxOutputTokens: options.maxOutputTokens,
safetySettings, safetySettings,
callbacks: [new N8nLlmTracing(this)], callbacks: [new N8nLlmTracing(this, { errorDescriptionMapper })],
onFailedAttempt: makeN8nLlmFailedAttemptHandler(this), onFailedAttempt: makeN8nLlmFailedAttemptHandler(this),
}); });

View file

@ -61,11 +61,15 @@ export class N8nLlmTracing extends BaseCallbackHandler {
totalTokens: completionTokens + promptTokens, totalTokens: completionTokens + promptTokens,
}; };
}, },
errorDescriptionMapper: (error: NodeError) => error.description,
}; };
constructor( constructor(
private executionFunctions: ISupplyDataFunctions, private executionFunctions: ISupplyDataFunctions,
options?: { tokensUsageParser: TokensUsageParser }, options?: {
tokensUsageParser?: TokensUsageParser;
errorDescriptionMapper?: (error: NodeError) => string;
},
) { ) {
super(); super();
this.options = { ...this.options, ...options }; this.options = { ...this.options, ...options };
@ -192,6 +196,10 @@ export class N8nLlmTracing extends BaseCallbackHandler {
} }
if (error instanceof NodeError) { if (error instanceof NodeError) {
if (this.options.errorDescriptionMapper) {
error.description = this.options.errorDescriptionMapper(error);
}
this.executionFunctions.addOutputData(this.connectionType, runDetails.index, error); this.executionFunctions.addOutputData(this.connectionType, runDetails.index, error);
} else { } else {
// If the error is not a NodeError, we wrap it in a NodeOperationError // If the error is not a NodeError, we wrap it in a NodeOperationError