NanoGPT: Pull max context and vision capability from endpoint
| @@ -1999,7 +1999,7 @@ | ||
| 1999 | 1999 | <strong data-i18n="enable_functions_desc_4">Not supported when Prompt Post-Processing with "no tools" is used!</strong> |
| 2000 | 2000 | </div> |
| 2001 | 2001 | </div> |
| 2002 | 2002 | <div class="range-block" data-source="openai,aimlapi,openrouter,mistralai,makersuite,vertexai,claude,custom,xai,pollinations,moonshot,cohere,cometapi,nanogpt"> |
| 2003 | 2003 | <label for="openai_image_inlining" class="checkbox_label flexWrap widthFreeExpand"> |
| 2004 | 2004 | <input id="openai_image_inlining" type="checkbox" /> |
| 2005 | 2005 | <span data-i18n="Send inline images">Send inline images</span> |
| @@ -4570,6 +4570,27 @@ function getFireworksMaxContext(model, isUnlocked) { | ||
| 4570 | 4570 | return max_32k; |
| 4571 | 4571 | } |
| 4572 | 4572 | |
| 4573 | +/** | |
| 4574 | + * Get the maximum context size for the NanoGPT model | |
| 4575 | + * @param {string} model Model identifier | |
| 4576 | + * @param {boolean} isUnlocked Whether context limits are unlocked | |
| 4577 | + * @returns {number} Maximum context size in tokens | |
| 4578 | + */ | |
| 4579 | +function getNanoGptMaxContext(model, isUnlocked) { | |
| 4580 | + if (isUnlocked) { | |
| 4581 | + return unlocked_max; | |
| 4582 | + } | |
| 4583 | + | |
| 4584 | + if (Array.isArray(model_list)) { | |
| 4585 | + const modelInfo = model_list.find(m => m.id === model); | |
| 4586 | + if (modelInfo?.context_length) { | |
| 4587 | + return modelInfo.context_length; | |
| 4588 | + } | |
| 4589 | + } | |
| 4590 | + | |
| 4591 | + return max_128k; | |
| 4592 | +} | |
| 4593 | + | |
| 4573 | 4594 | async function onModelChange() { |
| 4574 | 4595 | biasCache = undefined; |
| 4575 | 4596 | let value = String($(this).val() || ''); |
| @@ -4900,14 +4921,11 @@ async function onModelChange() { | ||
| 4900 | 4921 | } |
| 4901 | 4922 | |
| 4902 | 4923 | if (oai_settings.chat_completion_source === chat_completion_sources.NANOGPT) { |
| 4903 | - if (oai_settings.max_context_unlocked) { | |
| 4924 | + const maxContext = getNanoGptMaxContext(oai_settings.nanogpt_model, oai_settings.max_context_unlocked); | |
| 4904 | 4925 | $('#openai_max_context').attr('max', unlocked_maxmaxContext); |
| 4905 | - } else { | |
| 4906 | - $('#openai_max_context').attr('max', max_128k); | |
| 4907 | - } | |
| 4908 | - | |
| 4909 | 4926 | oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context); |
| 4910 | 4927 | $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); |
| 4928 | + oai_settings.temp_openai = Math.min(oai_max_temp, oai_settings.temp_openai); | |
| 4911 | 4929 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); |
| 4912 | 4930 | } |
| 4913 | 4931 | |
| @@ -5504,6 +5522,8 @@ export function isImageInliningSupported() { | ||
| 5504 | 5522 | return true; |
| 5505 | 5523 | case chat_completion_sources.MOONSHOT: |
| 5506 | 5524 | return visionSupportedModels.some(model => oai_settings.moonshot_model.includes(model)); |
| 5525 | + case chat_completion_sources.NANOGPT: | |
| 5526 | + return (Array.isArray(model_list) && model_list.find(m => m.id === oai_settings.nanogpt_model)?.capabilities?.vision); | |
| 5507 | 5527 | default: |
| 5508 | 5528 | return false; |
| 5509 | 5529 | } |
| @@ -2,6 +2,7 @@ import process from 'node:process'; | ||
| 2 | 2 | import util from 'node:util'; |
| 3 | 3 | import express from 'express'; |
| 4 | 4 | import fetch from 'node-fetch'; |
| 5 | +import urlJoin from 'url-join'; | |
| 5 | 6 | |
| 6 | 7 | import { |
| 7 | 8 | AIMLAPI_HEADERS, |
| @@ -1197,9 +1198,10 @@ export const router = express.Router(); | ||
| 1197 | 1198 | router.post('/status', async function (request, statusResponse) { |
| 1198 | 1199 | if (!request.body) return statusResponse.sendStatus(400); |
| 1199 | 1200 | |
| 1200 | 1201 | let apiUrl = ''; |
| 1201 | 1202 | let apiKey = ''; |
| 1202 | 1203 | let headers = {}; |
| 1204 | + let queryParams = {}; | |
| 1203 | 1205 | |
| 1204 | 1206 | if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) { |
| 1205 | 1207 | apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString(); |
| @@ -1227,12 +1229,13 @@ router.post('/status', async function (request, statusResponse) { | ||
| 1227 | 1229 | apiUrl = API_NANOGPT; |
| 1228 | 1230 | apiKey = readSecret(request.user.directories, SECRET_KEYS.NANOGPT); |
| 1229 | 1231 | headers = {}; |
| 1232 | + queryParams = { detailed: true }; | |
| 1230 | 1233 | } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.DEEPSEEK) { |
| 1231 | 1234 | apiUrl = new URL(request.body.reverse_proxy || API_DEEPSEEK.replace('/beta', '')).toString(); |
| 1232 | 1235 | apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.DEEPSEEK); |
| 1233 | 1236 | headers = {}; |
| 1234 | 1237 | } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.XAI) { |
| 1235 | 1238 | apiUrl = new URL(request.body.reverse_proxy || API_XAI).toString(); |
| 1236 | 1239 | apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.XAI); |
| 1237 | 1240 | headers = {}; |
| 1238 | 1241 | } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.AIMLAPI) { |
| @@ -1307,7 +1310,11 @@ router.post('/status', async function (request, statusResponse) { | ||
| 1307 | 1310 | } |
| 1308 | 1311 | |
| 1309 | 1312 | try { |
| 1310 | 1313 | const responsemodelsUrl = awaitnew fetchURL(urlJoin(apiUrl +, '/models', {)); |
| 1314 | + Object.keys(queryParams).forEach(key => { | |
| 1315 | + modelsUrl.searchParams.append(key, queryParams[key]); | |
| 1316 | + }); | |
| 1317 | + const response = await fetch(modelsUrl, { | |
| 1311 | 1318 | method: 'GET', |
| 1312 | 1319 | headers: { |
| 1313 | 1320 | 'Authorization': 'Bearer ' + apiKey, |