Auto-add OpenRouter captioning models

This commit is contained in:
Cohee
2024-09-15 18:38:44 +03:00
parent 44cc81fa73
commit 6393eda81e
3 changed files with 90 additions and 23 deletions

View File

@@ -1,6 +1,6 @@
import { ensureImageFormatSupported, getBase64Async, isTrueBoolean, saveBase64AsFile } from '../../utils.js'; import { ensureImageFormatSupported, getBase64Async, isTrueBoolean, saveBase64AsFile } from '../../utils.js';
import { getContext, getApiUrl, doExtrasFetch, extension_settings, modules, renderExtensionTemplateAsync } from '../../extensions.js'; import { getContext, getApiUrl, doExtrasFetch, extension_settings, modules, renderExtensionTemplateAsync } from '../../extensions.js';
import { appendMediaToMessage, callPopup, eventSource, event_types, getRequestHeaders, saveChatConditional, saveSettingsDebounced, substituteParamsExtended } from '../../../script.js'; import { appendMediaToMessage, callPopup, eventSource, event_types, getRequestHeaders, main_api, saveChatConditional, saveSettingsDebounced, substituteParamsExtended } from '../../../script.js';
import { getMessageTimeStamp } from '../../RossAscends-mods.js'; import { getMessageTimeStamp } from '../../RossAscends-mods.js';
import { SECRET_KEYS, secret_state } from '../../secrets.js'; import { SECRET_KEYS, secret_state } from '../../secrets.js';
import { getMultimodalCaption } from '../shared.js'; import { getMultimodalCaption } from '../shared.js';
@@ -431,14 +431,9 @@ jQuery(async function () {
$('#form_sheld').append(imgForm); $('#form_sheld').append(imgForm);
$('#img_file').on('change', (e) => onSelectImage(e.originalEvent, '', false)); $('#img_file').on('change', (e) => onSelectImage(e.originalEvent, '', false));
} }
function switchMultimodalBlocks() { async function switchMultimodalBlocks() {
await addOpenRouterModels();
const isMultimodal = extension_settings.caption.source === 'multimodal'; const isMultimodal = extension_settings.caption.source === 'multimodal';
$('#caption_ollama_pull').on('click', (e) => {
const presetModel = extension_settings.caption.multimodal_model !== 'ollama_current' ? extension_settings.caption.multimodal_model : '';
e.preventDefault();
$('#ollama_download_model').trigger('click');
$('#dialogue_popup_input').val(presetModel);
});
$('#caption_multimodal_block').toggle(isMultimodal); $('#caption_multimodal_block').toggle(isMultimodal);
$('#caption_prompt_block').toggle(isMultimodal); $('#caption_prompt_block').toggle(isMultimodal);
$('#caption_multimodal_api').val(extension_settings.caption.multimodal_api); $('#caption_multimodal_api').val(extension_settings.caption.multimodal_api);
@@ -448,30 +443,48 @@ jQuery(async function () {
const types = type.split(','); const types = type.split(',');
$(this).toggle(types.includes(extension_settings.caption.multimodal_api)); $(this).toggle(types.includes(extension_settings.caption.multimodal_api));
}); });
$('#caption_multimodal_api').on('change', () => {
const api = String($('#caption_multimodal_api').val());
const model = String($(`#caption_multimodal_model option[data-type="${api}"]`).first().val());
extension_settings.caption.multimodal_api = api;
extension_settings.caption.multimodal_model = model;
saveSettingsDebounced();
switchMultimodalBlocks();
});
$('#caption_multimodal_model').on('change', () => {
extension_settings.caption.multimodal_model = String($('#caption_multimodal_model').val());
saveSettingsDebounced();
});
} }
async function addSettings() { async function addSettings() {
const html = await renderExtensionTemplateAsync('caption', 'settings', { TEMPLATE_DEFAULT, PROMPT_DEFAULT }); const html = await renderExtensionTemplateAsync('caption', 'settings', { TEMPLATE_DEFAULT, PROMPT_DEFAULT });
$('#caption_container').append(html); $('#caption_container').append(html);
} }
async function addOpenRouterModels() {
const dropdown = document.getElementById('caption_multimodal_model');
if (!(dropdown instanceof HTMLSelectElement)) {
return;
}
if (extension_settings.caption.source !== 'multimodal' || extension_settings.caption.multimodal_api !== 'openrouter') {
return;
}
const options = Array.from(dropdown.options);
const response = await fetch('/api/openrouter/models/multimodal', {
method: 'POST',
headers: getRequestHeaders(),
});
if (!response.ok) {
return;
}
const modelIds = await response.json();
if (Array.isArray(modelIds) && modelIds.length > 0) {
modelIds.forEach((modelId) => {
if (!modelId || typeof modelId !== 'string' || options.some(o => o.value === modelId)) {
return;
}
const option = document.createElement('option');
option.value = modelId;
option.textContent = modelId;
option.dataset.type = 'openrouter';
dropdown.add(option);
});
}
}
await addSettings(); await addSettings();
addPictureSendForm(); addPictureSendForm();
addSendPictureButton(); addSendPictureButton();
setImageIcon(); setImageIcon();
migrateSettings(); migrateSettings();
switchMultimodalBlocks(); await switchMultimodalBlocks();
$('#caption_refine_mode').prop('checked', !!(extension_settings.caption.refine_mode)); $('#caption_refine_mode').prop('checked', !!(extension_settings.caption.refine_mode));
$('#caption_allow_reverse_proxy').prop('checked', !!(extension_settings.caption.allow_reverse_proxy)); $('#caption_allow_reverse_proxy').prop('checked', !!(extension_settings.caption.allow_reverse_proxy));
@@ -506,6 +519,24 @@ jQuery(async function () {
extension_settings.caption.auto_mode = !!$('#caption_auto_mode').prop('checked'); extension_settings.caption.auto_mode = !!$('#caption_auto_mode').prop('checked');
saveSettingsDebounced(); saveSettingsDebounced();
}); });
$('#caption_ollama_pull').on('click', (e) => {
const presetModel = extension_settings.caption.multimodal_model !== 'ollama_current' ? extension_settings.caption.multimodal_model : '';
e.preventDefault();
$('#ollama_download_model').trigger('click');
$('#dialogue_popup_input').val(presetModel);
});
$('#caption_multimodal_api').on('change', () => {
const api = String($('#caption_multimodal_api').val());
const model = String($(`#caption_multimodal_model option[data-type="${api}"]`).first().val());
extension_settings.caption.multimodal_api = api;
extension_settings.caption.multimodal_model = model;
saveSettingsDebounced();
switchMultimodalBlocks();
});
$('#caption_multimodal_model').on('change', () => {
extension_settings.caption.multimodal_model = String($('#caption_multimodal_model').val());
saveSettingsDebounced();
});
const onMessageEvent = async (index) => { const onMessageEvent = async (index) => {
if (!extension_settings.caption.auto_mode) { if (!extension_settings.caption.auto_mode) {
@@ -538,7 +569,8 @@ jQuery(async function () {
} }
}); });
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'caption', SlashCommandParser.addCommandObject(SlashCommand.fromProps({
name: 'caption',
callback: captionCommandCallback, callback: captionCommandCallback,
returns: 'caption', returns: 'caption',
namedArgumentList: [ namedArgumentList: [

View File

@@ -610,6 +610,9 @@ app.use('/api/search', require('./src/endpoints/search').router);
// Ooba/OpenAI text completions // Ooba/OpenAI text completions
app.use('/api/backends/text-completions', require('./src/endpoints/backends/text-completions').router); app.use('/api/backends/text-completions', require('./src/endpoints/backends/text-completions').router);
// OpenRouter
app.use('/api/openrouter', require('./src/endpoints/openrouter').router);
// KoboldAI // KoboldAI
app.use('/api/backends/kobold', require('./src/endpoints/backends/kobold').router); app.use('/api/backends/kobold', require('./src/endpoints/backends/kobold').router);

View File

@@ -0,0 +1,32 @@
const express = require('express');
const { jsonParser } = require('../express-common');
const router = express.Router();
const API_OPENROUTER = 'https://openrouter.ai/api/v1';
router.post('/models/multimodal', jsonParser, async (_req, res) => {
try {
// The endpoint is available without authentication
const response = await fetch(`${API_OPENROUTER}/models`, {
method: 'GET',
headers: {
'Accept': 'application/json',
},
});
if (!response.ok) {
return res.json([]);
}
const data = await response.json();
const models = data?.data || [];
const multimodalModels = models.filter(m => m?.architecture?.modality === 'text+image->text').map(m => m.id);
return res.json(multimodalModels);
} catch (error) {
console.error(error);
return res.sendStatus(500);
}
});
module.exports = { router };