message inlining vision support

This commit is contained in:
based
2023-12-15 01:28:54 +10:00
parent 178b07f414
commit d5bcd96eef
3 changed files with 57 additions and 28 deletions

View File

@ -31,18 +31,18 @@ import {
system_message_types, system_message_types,
this_chid, this_chid,
} from '../script.js'; } from '../script.js';
import { groups, selected_group } from './group-chats.js'; import {groups, selected_group} from './group-chats.js';
import { import {
chatCompletionDefaultPrompts, chatCompletionDefaultPrompts,
INJECTION_POSITION, INJECTION_POSITION,
Prompt, Prompt,
promptManagerDefaultPromptOrders,
PromptManager, PromptManager,
promptManagerDefaultPromptOrders,
} from './PromptManager.js'; } from './PromptManager.js';
import { getCustomStoppingStrings, persona_description_positions, power_user } from './power-user.js'; import {getCustomStoppingStrings, persona_description_positions, power_user} from './power-user.js';
import { SECRET_KEYS, secret_state, writeSecret } from './secrets.js'; import {SECRET_KEYS, secret_state, writeSecret} from './secrets.js';
import EventSourceStream from './sse-stream.js'; import EventSourceStream from './sse-stream.js';
import { import {
@ -56,7 +56,7 @@ import {
resetScrollHeight, resetScrollHeight,
stringFormat, stringFormat,
} from './utils.js'; } from './utils.js';
import { countTokensOpenAI, getTokenizerModel } from './tokenizers.js'; import {countTokensOpenAI, getTokenizerModel} from './tokenizers.js';
import { import {
formatInstructModeChat, formatInstructModeChat,
formatInstructModeExamples, formatInstructModeExamples,
@ -1795,13 +1795,15 @@ class Message {
async addImage(image) { async addImage(image) {
const textContent = this.content; const textContent = this.content;
const isDataUrl = isDataURL(image); const isDataUrl = isDataURL(image);
if (!isDataUrl) { if (!isDataUrl) {
try { try {
const response = await fetch(image, { method: 'GET', cache: 'force-cache' }); const response = await fetch(image, { method: 'GET', cache: 'force-cache' });
if (!response.ok) throw new Error('Failed to fetch image'); if (!response.ok) throw new Error('Failed to fetch image');
const blob = await response.blob(); const blob = await response.blob();
image = await getBase64Async(blob); image = await getBase64Async(blob);
if (oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE) {
image = image.split(',')[1];
}
} catch (error) { } catch (error) {
console.error('Image adding skipped', error); console.error('Image adding skipped', error);
return; return;
@ -3087,7 +3089,8 @@ async function onModelChange() {
} else { } else {
$('#openai_max_context').attr('max', max_8k); $('#openai_max_context').attr('max', max_8k);
} }
oai_settings.temp_openai = Math.min(claude_max_temp, oai_settings.temp_openai);
$('#temp_openai').attr('max', claude_max_temp).val(oai_settings.temp_openai).trigger('input');
oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context); oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context);
$('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input');
} }
@ -3435,7 +3438,7 @@ export function isImageInliningSupported() {
case chat_completion_sources.OPENAI: case chat_completion_sources.OPENAI:
return oai_settings.openai_model.includes(gpt4v); return oai_settings.openai_model.includes(gpt4v);
case chat_completion_sources.MAKERSUITE: case chat_completion_sources.MAKERSUITE:
return oai_settings.openai_model.includes(geminiProV); return oai_settings.google_model.includes(geminiProV);
case chat_completion_sources.OPENROUTER: case chat_completion_sources.OPENROUTER:
return oai_settings.openrouter_model.includes(gpt4v) || oai_settings.openrouter_model.includes(llava13b); return oai_settings.openrouter_model.includes(gpt4v) || oai_settings.openrouter_model.includes(llava13b);
default: default:

View File

@ -1002,6 +1002,9 @@ async function sendMakerSuiteRequest(request, response) {
return response.status(400).send({ error: true }); return response.status(400).send({ error: true });
} }
const google_model = request.body.model;
const should_stream = request.body.stream;
const generationConfig = { const generationConfig = {
stopSequences: request.body.stop, stopSequences: request.body.stop,
candidateCount: 1, candidateCount: 1,
@ -1012,13 +1015,11 @@ async function sendMakerSuiteRequest(request, response) {
}; };
const body = { const body = {
contents: convertGooglePrompt(request.body.messages), contents: convertGooglePrompt(request.body.messages, google_model),
safetySettings: MAKERSUITE_SAFETY, safetySettings: MAKERSUITE_SAFETY,
generationConfig: generationConfig, generationConfig: generationConfig,
}; };
const google_model = request.body.model;
const should_stream = request.body.stream;
try { try {
const controller = new AbortController(); const controller = new AbortController();
request.socket.removeAllListeners('close'); request.socket.removeAllListeners('close');

View File

@ -72,31 +72,56 @@ function convertClaudePrompt(messages, addHumanPrefix, addAssistantPostfix, with
return requestPrompt; return requestPrompt;
} }
function convertGooglePrompt(messages) { function convertGooglePrompt(messages, type) {
const contents = []; const contents = [];
let lastRole = ''; let lastRole = '';
let currentText = ''; let currentText = '';
messages.forEach((message, index) => {
const role = message.role === 'assistant' ? 'model' : 'user'; const isMultimodal = type === 'gemini-pro-vision';
if (lastRole === role) {
currentText += '\n\n' + message.content; if (isMultimodal) {
} else { const combinedText = messages.map((message) => {
if (currentText !== '') { const role = message.role === 'assistant' ? 'MODEL: ' : 'USER: ';
return role + message.content;
}).join('\n\n').trim();
const imageEntry = messages.find((message) => message.content[1]?.image_url);
contents.push({
parts: [
{ text: combinedText },
{
inlineData: {
mimeType: 'image/png',
data: imageEntry.content[1].image_url.url ?? '',
},
},
],
role: 'user',
});
} else {
messages.forEach((message, index) => {
const role = message.role === 'assistant' ? 'model' : 'user';
if (lastRole === role) {
currentText += '\n\n' + message.content;
} else {
if (currentText !== '') {
contents.push({
parts: [{ text: currentText.trim() }],
role: lastRole,
});
}
currentText = message.content;
lastRole = role;
}
if (index === messages.length - 1) {
contents.push({ contents.push({
parts: [{ text: currentText.trim() }], parts: [{ text: currentText.trim() }],
role: lastRole, role: lastRole,
}); });
} }
currentText = message.content; });
lastRole = role; }
}
if (index === messages.length - 1) {
contents.push({
parts: [{ text: currentText.trim() }],
role: lastRole,
});
}
});
return contents; return contents;
} }