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