mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Allow prompt post-processing for all sources. Add 'single user msg' processing (#4009)
* Allow prompt post-processing for all sources. Add 'single user msg' PPP type * Fix copilot comments * Fix typo in element id * Remove redundant conditions * Lint fix * Add link to PPP docs
This commit is contained in:
@ -1991,6 +1991,7 @@
|
||||
<div class="flexBasis100p toggle-description justifyLeft">
|
||||
<span data-i18n="enable_functions_desc_1">Allows using </span><a href="https://platform.openai.com/docs/guides/function-calling" target="_blank" data-i18n="enable_functions_desc_2">function tools</a>.
|
||||
<span data-i18n="enable_functions_desc_3">Can be utilized by various extensions to provide additional functionality.</span>
|
||||
<strong data-i18n="enable_functions_desc_4">Not supported when Prompt Post-Processing is used!</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="range-block" data-source="openai,openrouter,mistralai,makersuite,vertexai,claude,custom,01ai,xai,pollinations">
|
||||
@ -3535,13 +3536,21 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="prompt_post_porcessing_form" data-source="custom,openrouter">
|
||||
<h4 data-i18n="Prompt Post-Processing">Prompt Post-Processing</h4>
|
||||
<div id="prompt_post_processing_form">
|
||||
<h4>
|
||||
<span data-i18n="Prompt Post-Processing">
|
||||
Prompt Post-Processing
|
||||
</span>
|
||||
<a href="https://docs.sillytavern.app/usage/api-connections/openai/#prompt-post-processing" class="notes-link" target="_blank">
|
||||
<span class="fa-solid fa-circle-question note-link-span"></span>
|
||||
</a>
|
||||
</h4>
|
||||
<select id="custom_prompt_post_processing" class="text_pole" title="Applies additional processing to the prompt before sending it to the API." data-i18n="[title]Applies additional processing to the prompt before sending it to the API.">
|
||||
<option data-i18n="prompt_post_processing_none" value="">None</option>
|
||||
<option data-i18n="prompt_post_processing_merge" value="merge">Merge consecutive roles</option>
|
||||
<option data-i18n="prompt_post_processing_semi" value="semi">Semi-strict (alternating roles)</option>
|
||||
<option data-i18n="prompt_post_processing_strict" value="strict">Strict (user first, alternating roles)</option>
|
||||
<option data-i18n="prompt_post_processing_single" value="single">Single user message</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-container flex">
|
||||
|
@ -203,13 +203,14 @@ const continue_postfix_types = {
|
||||
DOUBLE_NEWLINE: '\n\n',
|
||||
};
|
||||
|
||||
const custom_prompt_post_processing_types = {
|
||||
export const custom_prompt_post_processing_types = {
|
||||
NONE: '',
|
||||
/** @deprecated Use MERGE instead. */
|
||||
CLAUDE: 'claude',
|
||||
MERGE: 'merge',
|
||||
SEMI: 'semi',
|
||||
STRICT: 'strict',
|
||||
SINGLE: 'single',
|
||||
};
|
||||
|
||||
const openrouter_middleout_types = {
|
||||
|
@ -575,6 +575,11 @@ export class ToolManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Post-processing will forcefully remove past tool calls from the prompt, making them useless
|
||||
if (oai_settings.custom_prompt_post_processing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (oai_settings.chat_completion_source === chat_completion_sources.POLLINATIONS && Array.isArray(model_list)) {
|
||||
const currentModel = model_list.find(model => model.id === oai_settings.pollinations_model);
|
||||
if (currentModel) {
|
||||
|
@ -72,15 +72,17 @@ function postProcessPrompt(messages, type, names) {
|
||||
switch (type) {
|
||||
case 'merge':
|
||||
case 'claude':
|
||||
return mergeMessages(messages, names, false, false);
|
||||
return mergeMessages(messages, names, { strict: false, placeholders: false, single: false });
|
||||
case 'semi':
|
||||
return mergeMessages(messages, names, true, false);
|
||||
return mergeMessages(messages, names, { strict: true, placeholders: false, single: false });
|
||||
case 'strict':
|
||||
return mergeMessages(messages, names, true, true);
|
||||
return mergeMessages(messages, names, { strict: true, placeholders: true, single: false });
|
||||
case 'deepseek':
|
||||
return addAssistantPrefix(mergeMessages(messages, names, true, false));
|
||||
return addAssistantPrefix(mergeMessages(messages, names, { strict: true, placeholders: false, single: false }));
|
||||
case 'deepseek-reasoner':
|
||||
return addAssistantPrefix(mergeMessages(messages, names, true, true));
|
||||
return addAssistantPrefix(mergeMessages(messages, names, { strict: true, placeholders: true, single: false }));
|
||||
case 'single':
|
||||
return mergeMessages(messages, names, { strict: true, placeholders: false, single: true });
|
||||
default:
|
||||
return messages;
|
||||
}
|
||||
@ -1206,6 +1208,15 @@ router.post('/bias', async function (request, response) {
|
||||
router.post('/generate', function (request, response) {
|
||||
if (!request.body) return response.status(400).send({ error: true });
|
||||
|
||||
const postProcessingType = request.body.custom_prompt_post_processing;
|
||||
if (Array.isArray(request.body.messages) && postProcessingType) {
|
||||
console.info('Applying custom prompt post-processing of type', postProcessingType);
|
||||
request.body.messages = postProcessPrompt(
|
||||
request.body.messages,
|
||||
postProcessingType,
|
||||
getPromptNames(request));
|
||||
}
|
||||
|
||||
switch (request.body.chat_completion_source) {
|
||||
case CHAT_COMPLETION_SOURCES.CLAUDE: return sendClaudeRequest(request, response);
|
||||
case CHAT_COMPLETION_SOURCES.SCALE: return sendScaleRequest(request, response);
|
||||
@ -1224,15 +1235,6 @@ router.post('/generate', function (request, response) {
|
||||
let bodyParams;
|
||||
const isTextCompletion = Boolean(request.body.model && TEXT_COMPLETION_MODELS.includes(request.body.model)) || typeof request.body.messages === 'string';
|
||||
|
||||
const postProcessTypes = [CHAT_COMPLETION_SOURCES.CUSTOM, CHAT_COMPLETION_SOURCES.OPENROUTER];
|
||||
if (Array.isArray(request.body.messages) && postProcessTypes.includes(request.body.chat_completion_source) && request.body.custom_prompt_post_processing) {
|
||||
console.info('Applying custom prompt post-processing of type', request.body.custom_prompt_post_processing);
|
||||
request.body.messages = postProcessPrompt(
|
||||
request.body.messages,
|
||||
request.body.custom_prompt_post_processing,
|
||||
getPromptNames(request));
|
||||
}
|
||||
|
||||
if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {
|
||||
apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString();
|
||||
apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI);
|
||||
|
@ -695,11 +695,13 @@ export function convertXAIMessages(messages, names) {
|
||||
* Merge messages with the same consecutive role, removing names if they exist.
|
||||
* @param {any[]} messages Messages to merge
|
||||
* @param {PromptNames} names Prompt names
|
||||
* @param {boolean} strict Enable strict mode: only allow one system message at the start, force user first message
|
||||
* @param {boolean} placeholders Add user placeholders to the messages in strict mode
|
||||
* @param {object} options Options for merging
|
||||
* @param {boolean} [options.strict] Enable strict mode: only allow one system message at the start, force user first message
|
||||
* @param {boolean} [options.placeholders] Add user placeholders to the messages in strict mode
|
||||
* @param {boolean} [options.single] Force every role to be user, merging all messages into one
|
||||
* @returns {any[]} Merged messages
|
||||
*/
|
||||
export function mergeMessages(messages, names, strict, placeholders) {
|
||||
export function mergeMessages(messages, names, { strict = false, placeholders = false, single = false } = {}) {
|
||||
let mergedMessages = [];
|
||||
|
||||
/** @type {Map<string,object>} */
|
||||
@ -744,6 +746,20 @@ export function mergeMessages(messages, names, strict, placeholders) {
|
||||
if (message.role === 'tool') {
|
||||
message.role = 'user';
|
||||
}
|
||||
if (single) {
|
||||
if (message.role === 'assistant') {
|
||||
if (names.charName && !message.content.startsWith(`${names.charName}: `) && !names.startsWithGroupName(message.content)) {
|
||||
message.content = `${names.charName}: ${message.content}`;
|
||||
}
|
||||
}
|
||||
if (message.role === 'user') {
|
||||
if (names.userName && !message.content.startsWith(`${names.userName}: `)) {
|
||||
message.content = `${names.userName}: ${message.content}`;
|
||||
}
|
||||
}
|
||||
|
||||
message.role = 'user';
|
||||
}
|
||||
delete message.name;
|
||||
delete message.tool_calls;
|
||||
delete message.tool_call_id;
|
||||
@ -807,7 +823,7 @@ export function mergeMessages(messages, names, strict, placeholders) {
|
||||
mergedMessages.unshift({ role: 'user', content: PROMPT_PLACEHOLDER });
|
||||
}
|
||||
}
|
||||
return mergeMessages(mergedMessages, names, false, placeholders);
|
||||
return mergeMessages(mergedMessages, names, { strict: false, placeholders, single: false });
|
||||
}
|
||||
|
||||
return mergedMessages;
|
||||
|
Reference in New Issue
Block a user