From ef59e8abae74486de590690c5628593f03b764c6 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 25 Jul 2024 21:04:57 +0300 Subject: [PATCH] #2557 Improve Mistral prompt conversion --- src/endpoints/backends/chat-completions.js | 2 +- src/prompt-converters.js | 46 +++++++--------------- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/src/endpoints/backends/chat-completions.js b/src/endpoints/backends/chat-completions.js index e4b20de33..2177e0c12 100644 --- a/src/endpoints/backends/chat-completions.js +++ b/src/endpoints/backends/chat-completions.js @@ -483,7 +483,7 @@ async function sendMistralAIRequest(request, response) { } try { - const messages = convertMistralMessages(request.body.messages, request.body.model, request.body.char_name, request.body.user_name); + const messages = convertMistralMessages(request.body.messages, request.body.char_name, request.body.user_name); const controller = new AbortController(); request.socket.removeAllListeners('close'); request.socket.on('close', function () { diff --git a/src/prompt-converters.js b/src/prompt-converters.js index b42246e44..33d109faa 100644 --- a/src/prompt-converters.js +++ b/src/prompt-converters.js @@ -364,65 +364,49 @@ function convertGooglePrompt(messages, model, useSysPrompt = false, charName = ' /** * Convert a prompt from the ChatML objects to the format used by MistralAI. * @param {object[]} messages Array of messages - * @param {string} model Model name * @param {string} charName Character name * @param {string} userName User name */ -function convertMistralMessages(messages, model, charName = '', userName = '') { +function convertMistralMessages(messages, charName = '', userName = '') { if (!Array.isArray(messages)) { return []; } - //large seems to be throwing a 500 error if we don't make the first message a user role, most likely a bug since the other models won't do this - if (model.includes('large')) { - messages[0].role = 'user'; - } - - //must send a user role as last message + // Make the last assistant message a prefill const lastMsg = messages[messages.length - 1]; - if (messages.length > 0 && lastMsg && (lastMsg.role === 'system' || lastMsg.role === 'assistant')) { - if (lastMsg.role === 'assistant' && lastMsg.name) { - lastMsg.content = lastMsg.name + ': ' + lastMsg.content; - } else if (lastMsg.role === 'system') { - lastMsg.content = '[INST] ' + lastMsg.content + ' [/INST]'; - } - lastMsg.role = 'user'; + if (messages.length > 0 && lastMsg && (lastMsg.role === 'assistant')) { + lastMsg.prefix = true; } - //system prompts can be stacked at the start, but any futher sys prompts after the first user/assistant message will break the model - let encounteredNonSystemMessage = false; + // Doesn't support completion names, so prepend if not already done by the frontend (e.g. for group chats). messages.forEach(msg => { if (msg.role === 'system' && msg.name === 'example_assistant') { - if (charName) { + if (charName && !msg.content.startsWith(`${charName}: `)) { msg.content = `${charName}: ${msg.content}`; } delete msg.name; } if (msg.role === 'system' && msg.name === 'example_user') { - if (userName) { + if (userName && !msg.content.startsWith(`${userName}: `)) { msg.content = `${userName}: ${msg.content}`; } delete msg.name; } - if (msg.name) { + if (msg.name && msg.role !== 'system' && !msg.content.startsWith(`${msg.name}: `)) { msg.content = `${msg.name}: ${msg.content}`; delete msg.name; } - - if ((msg.role === 'user' || msg.role === 'assistant') && !encounteredNonSystemMessage) { - encounteredNonSystemMessage = true; - } - - if (encounteredNonSystemMessage && msg.role === 'system') { - msg.role = 'user'; - //unsure if the instruct version is what they've deployed on their endpoints and if this will make a difference or not. - //it should be better than just sending the message as a user role without context though - msg.content = '[INST] ' + msg.content + ' [/INST]'; - } }); + // If system role message immediately follows an assistant message, change its role to user + for (let i = 0; i < messages.length - 1; i++) { + if (messages[i].role === 'assistant' && messages[i + 1].role === 'system') { + messages[i + 1].role = 'user'; + } + } + return messages; }