diff --git a/default/config.yaml b/default/config.yaml index 1d5e8dc3b..e7fe7e196 100644 --- a/default/config.yaml +++ b/default/config.yaml @@ -234,6 +234,10 @@ claude: # should be ideal for most use cases. # Any value other than a non-negative integer will be ignored and caching at depth will not be enabled. cachingAtDepth: -1 +# -- GOOGLE GEMINI API CONFIGURATION -- +gemini: + # API endpoint version ("v1beta" or "v1alpha") + apiVersion: 'v1beta' # -- SERVER PLUGIN CONFIGURATION -- enableServerPlugins: false # Attempt to automatically update server plugins on startup diff --git a/public/index.html b/public/index.html index f708229d4..4f57d80b4 100644 --- a/public/index.html +++ b/public/index.html @@ -2025,7 +2025,7 @@ Use system prompt - +
@@ -3146,49 +3146,49 @@

Google Model

diff --git a/public/scripts/extensions/caption/settings.html b/public/scripts/extensions/caption/settings.html index 539a737ef..8b767ca13 100644 --- a/public/scripts/extensions/caption/settings.html +++ b/public/scripts/extensions/caption/settings.html @@ -79,34 +79,33 @@ - - - - - + + + - - - - - - - - - - - - - - - + + + + + + + + - - - + + + + + + + + + + + diff --git a/public/scripts/openai.js b/public/scripts/openai.js index 2eb809a92..d1b996c37 100644 --- a/public/scripts/openai.js +++ b/public/scripts/openai.js @@ -4481,20 +4481,16 @@ async function onModelChange() { if (oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE) { if (oai_settings.max_context_unlocked) { $('#openai_max_context').attr('max', max_2mil); - } else if (value.includes('gemini-exp-1114') || value.includes('gemini-exp-1121') || value.includes('gemini-2.0-flash-thinking-exp-1219')) { - $('#openai_max_context').attr('max', max_32k); - } else if (value.includes('gemini-1.5-pro') || value.includes('gemini-exp-1206') || value.includes('gemini-2.0-pro')) { + } else if (value.includes('gemini-1.5-pro')) { $('#openai_max_context').attr('max', max_2mil); - } else if (value.includes('gemini-1.5-flash') || value.includes('gemini-2.0-flash') || value.includes('gemini-2.5-flash-preview-04-17') || value.includes('gemini-2.5-pro-exp-03-25') || value.includes('gemini-2.5-pro-preview-03-25')) { + } else if (value.includes('gemini-1.5-flash') || value.includes('gemini-2.0-flash') || value.includes('gemini-2.0-pro') || value.includes('gemini-exp') || value.includes('gemini-2.5-flash') || value.includes('gemini-2.5-pro') || value.includes('learnlm-2.0-flash')) { $('#openai_max_context').attr('max', max_1mil); - } else if (value.includes('gemini-1.0-pro') || value === 'gemini-pro') { - $('#openai_max_context').attr('max', max_32k); - } else if (value.includes('gemini-1.0-ultra') || value === 'gemini-ultra') { - $('#openai_max_context').attr('max', max_32k); - } else if (value.includes('gemma-3')) { + } else if (value.includes('gemma-3-27b-it')) { $('#openai_max_context').attr('max', max_128k); + } else if (value.includes('gemma-3') || value.includes('learnlm-1.5-pro-experimental')) { + $('#openai_max_context').attr('max', max_32k); } else { - $('#openai_max_context').attr('max', max_4k); + $('#openai_max_context').attr('max', max_32k); } let makersuite_max_temp = (value.includes('vision') || value.includes('ultra') || value.includes('gemma')) ? 1.0 : 2.0; oai_settings.temp_openai = Math.min(makersuite_max_temp, oai_settings.temp_openai); @@ -5152,9 +5148,8 @@ export function isImageInliningSupported() { 'gemini-1.5', 'gemini-2.0', 'gemini-2.5', - 'gemini-exp-1114', - 'gemini-exp-1121', 'gemini-exp-1206', + 'learnlm', // MistralAI 'mistral-small-2503', 'mistral-small-latest', @@ -5168,7 +5163,7 @@ export function isImageInliningSupported() { case chat_completion_sources.OPENAI: return visionSupportedModels.some(model => oai_settings.openai_model.includes(model) - && ['gpt-4-turbo-preview', 'o1-mini', 'o3-mini'].some(x => !oai_settings.openai_model.includes(x)) + && ['gpt-4-turbo-preview', 'o1-mini', 'o3-mini'].some(x => !oai_settings.openai_model.includes(x)), ); case chat_completion_sources.MAKERSUITE: return visionSupportedModels.some(model => oai_settings.google_model.includes(model)); diff --git a/src/constants.js b/src/constants.js index 64b9330b2..3b18e732f 100644 --- a/src/constants.js +++ b/src/constants.js @@ -156,7 +156,7 @@ export const GEMINI_SAFETY = [ }, { category: 'HARM_CATEGORY_CIVIC_INTEGRITY', - threshold: 'BLOCK_NONE', + threshold: 'OFF', }, ]; diff --git a/src/endpoints/backends/chat-completions.js b/src/endpoints/backends/chat-completions.js index adc62e641..e440d6c01 100644 --- a/src/endpoints/backends/chat-completions.js +++ b/src/endpoints/backends/chat-completions.js @@ -343,8 +343,8 @@ async function sendMakerSuiteRequest(request, response) { const enableWebSearch = Boolean(request.body.enable_web_search); const requestImages = Boolean(request.body.request_images); const reasoningEffort = String(request.body.reasoning_effort); - const isThinking = model.includes('thinking'); const isGemma = model.includes('gemma'); + const isLearnLM = model.includes('learnlm'); const generationConfig = { stopSequences: request.body.stop, @@ -358,48 +358,60 @@ async function sendMakerSuiteRequest(request, response) { }; function getGeminiBody() { + // #region UGLY MODEL LISTS AREA + const imageGenerationModels = [ + 'gemini-2.0-flash-exp', + 'gemini-2.0-flash-exp-image-generation', + ]; + + // These models do not support setting the threshold to OFF at all. + const blockNoneModels = [ + 'gemini-1.5-pro-001', + 'gemini-1.5-flash-001', + 'gemini-1.5-flash-8b-exp-0827', + 'gemini-1.5-flash-8b-exp-0924', + ]; + + const thinkingBudgetModels = [ + 'gemini-2.5-flash-preview-04-17', + ]; + + const noSearchModels = [ + 'gemini-2.0-flash-lite', + 'gemini-2.0-flash-lite-001', + 'gemini-2.0-flash-lite-preview-02-05', + 'gemini-1.5-flash-8b-exp-0924', + 'gemini-1.5-flash-8b-exp-0827', + ]; + // #endregion + if (!Array.isArray(generationConfig.stopSequences) || !generationConfig.stopSequences.length) { delete generationConfig.stopSequences; } - const useMultiModal = requestImages && ['gemini-2.0-flash-exp', 'gemini-2.0-flash-exp-image-generation'].includes(model); - if (useMultiModal) { + const enableImageModality = requestImages && imageGenerationModels.includes(model); + if (enableImageModality) { generationConfig.responseModalities = ['text', 'image']; } - const useSystemPrompt = !useMultiModal && ( - model.includes('gemini-2.5-pro') || - model.includes('gemini-2.5-flash') || - model.includes('gemini-2.0-pro') || - model.includes('gemini-2.0-flash') || - model.includes('gemini-2.0-flash-thinking-exp') || - model.includes('gemini-1.5-flash') || - model.includes('gemini-1.5-pro') || - model.startsWith('gemini-exp') - ) && request.body.use_makersuite_sysprompt; + const useSystemPrompt = !enableImageModality && !isGemma && request.body.use_makersuite_sysprompt; const tools = []; const prompt = convertGooglePrompt(request.body.messages, model, useSystemPrompt, getPromptNames(request)); let safetySettings = GEMINI_SAFETY; - // These models do not support setting the threshold to OFF at all. - if (['gemini-1.5-pro-001', 'gemini-1.5-flash-001', 'gemini-1.5-flash-8b-exp-0827', 'gemini-1.5-flash-8b-exp-0924', 'gemini-pro', 'gemini-1.0-pro', 'gemini-1.0-pro-001', 'gemma-3-27b-it'].includes(model)) { + if (blockNoneModels.includes(model)) { safetySettings = GEMINI_SAFETY.map(setting => ({ ...setting, threshold: 'BLOCK_NONE' })); } - // Interestingly, Gemini 2.0 Flash does support setting the threshold for HARM_CATEGORY_CIVIC_INTEGRITY to OFF. - else if (['gemini-2.0-flash', 'gemini-2.0-flash-001', 'gemini-2.0-flash-exp', 'gemini-2.0-flash-exp-image-generation'].includes(model)) { - safetySettings = GEMINI_SAFETY.map(setting => ({ ...setting, threshold: 'OFF' })); - } - // Most of the other models allow for setting the threshold of filters, except for HARM_CATEGORY_CIVIC_INTEGRITY, to OFF. - if (enableWebSearch && !useMultiModal && !isGemma) { - const searchTool = model.includes('1.5') || model.includes('1.0') + if (enableWebSearch && !enableImageModality && !isGemma && !isLearnLM && !noSearchModels.includes(model)) { + const searchTool = model.includes('1.5') ? ({ google_search_retrieval: {} }) : ({ google_search: {} }); tools.push(searchTool); } - if (Array.isArray(request.body.tools) && request.body.tools.length > 0 && !useMultiModal && !isGemma) { + if (Array.isArray(request.body.tools) && request.body.tools.length > 0 && !enableImageModality && !isGemma) { const functionDeclarations = []; for (const tool of request.body.tools) { if (tool.type === 'function') { @@ -415,11 +427,6 @@ async function sendMakerSuiteRequest(request, response) { tools.push({ function_declarations: functionDeclarations }); } - // One more models list to maintain, yay - const thinkingBudgetModels = [ - 'gemini-2.5-flash-preview-04-17', - ]; - if (thinkingBudgetModels.includes(model)) { const thinkingBudget = calculateGoogleBudgetTokens(generationConfig.maxOutputTokens, reasoningEffort); @@ -455,7 +462,7 @@ async function sendMakerSuiteRequest(request, response) { controller.abort(); }); - const apiVersion = isThinking ? 'v1alpha' : 'v1beta'; + const apiVersion = getConfigValue('gemini.apiVersion', 'v1beta'); const responseType = (stream ? 'streamGenerateContent' : 'generateContent'); const generateResponse = await fetch(`${apiUrl.toString().replace(/\/$/, '')}/${apiVersion}/models/${model}:${responseType}?key=${apiKey}${stream ? '&alt=sse' : ''}`, { @@ -466,7 +473,7 @@ async function sendMakerSuiteRequest(request, response) { }, signal: controller.signal, }); - // have to do this because of their busted ass streaming endpoint + if (stream) { try { // Pipe remote SSE stream to Express response