From 3790e82ef3ed9d8995f4d2999d0d136d449d5b62 Mon Sep 17 00:00:00 2001 From: shiro-yama Date: Mon, 10 Mar 2025 11:59:14 +0800 Subject: [PATCH] fix: fix GeminiProvdier config tools has empty array or object make request 400 (#3090) Co-authored-by: archer --- src/renderer/src/providers/GeminiProvider.ts | 6 +++- src/renderer/src/providers/geminiToolUtils.ts | 31 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/renderer/src/providers/geminiToolUtils.ts diff --git a/src/renderer/src/providers/GeminiProvider.ts b/src/renderer/src/providers/GeminiProvider.ts index 5a3ac559..db1258b7 100644 --- a/src/renderer/src/providers/GeminiProvider.ts +++ b/src/renderer/src/providers/GeminiProvider.ts @@ -27,6 +27,7 @@ import OpenAI from 'openai' import { CompletionsParams } from '.' import BaseProvider from './BaseProvider' +import { filterInvalidTools } from './geminiToolUtils' import { callMCPTool, filterMCPTools, @@ -181,7 +182,6 @@ export default class GeminiProvider extends BaseProvider { { model: model.id, systemInstruction: assistant.prompt, - tools: tools.length > 0 ? tools : undefined, safetySettings: this.getSafetySettings(model.id), generationConfig: { maxOutputTokens: maxTokens, @@ -192,6 +192,10 @@ export default class GeminiProvider extends BaseProvider { }, this.requestOptions ) + const filteredTools = filterInvalidTools(geminiModel.tools) + if (!isEmpty(filteredTools)) { + geminiModel.tools = filteredTools + } const chat = geminiModel.startChat({ history }) const messageContents = await this.getMessageContents(userLastMessage!) diff --git a/src/renderer/src/providers/geminiToolUtils.ts b/src/renderer/src/providers/geminiToolUtils.ts new file mode 100644 index 00000000..2b2da6a8 --- /dev/null +++ b/src/renderer/src/providers/geminiToolUtils.ts @@ -0,0 +1,31 @@ +import { CodeExecutionTool, FunctionDeclarationsTool, GoogleSearchRetrievalTool, Tool } from '@google/generative-ai' +import { isEmpty } from 'lodash' + +export function filterInvalidTools(tools: Tool[] | undefined) { + return tools?.filter((e) => !isToolInvalid(e)) ?? [] +} + +function isToolInvalid(tool: Tool | undefined) { + if (tool == undefined) return true + if (isCodeExecutionTool(tool)) { + return isEmpty(tool.codeExecution) + } else if (isGoogleSearchRetrievalTool(tool)) { + return isEmpty(tool.googleSearchRetrieval) + } else if (isFunctionDeclarationsTool(tool)) { + return isEmpty(tool.functionDeclarations) + } else { + return true + } +} + +function isCodeExecutionTool(tool: Tool): tool is CodeExecutionTool { + return (tool as CodeExecutionTool).codeExecution !== undefined +} + +function isGoogleSearchRetrievalTool(tool: Tool): tool is GoogleSearchRetrievalTool { + return (tool as GoogleSearchRetrievalTool).googleSearchRetrieval !== undefined +} + +function isFunctionDeclarationsTool(tool: Tool): tool is FunctionDeclarationsTool { + return (tool as FunctionDeclarationsTool).functionDeclarations !== undefined +}