Merge pull request #3721 from SillyTavern/or-prompt-post-processing OpenRouter: Allow applying prompt post-processing

fb2f8dce10a5568e4b1f5c3369a97ef5b4a4f54c

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
3 files changed, +19 -16Ignore whitespace
public/index.html+9 -7
@@ -3415,13 +3415,6 @@
3415 <div class="flex-container">3415 <div class="flex-container">
3416 <select id="model_custom_select" class="text_pole model_custom_select"></select>3416 <select id="model_custom_select" class="text_pole model_custom_select"></select>
3417 </div>3417 </div>
3418 <h4 data-i18n="Prompt Post-Processing">Prompt Post-Processing</h4>
3419 <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.">
3420 <option data-i18n="prompt_post_processing_none" value="">None</option>
3421 <option data-i18n="prompt_post_processing_merge" value="merge">Merge consecutive roles</option>
3422 <option data-i18n="prompt_post_processing_semi" value="semi">Semi-strict (alternating roles)</option>
3423 <option data-i18n="prompt_post_processing_strict" value="strict">Strict (user first, alternating roles)</option>
3424 </select>
3425 </form>3418 </form>
3426 <div id="01ai_form" data-source="01ai">3419 <div id="01ai_form" data-source="01ai">
3427 <h4>3420 <h4>
@@ -3440,6 +3433,15 @@
3440 <select id="model_01ai_select">3433 <select id="model_01ai_select">
3441 </select>3434 </select>
3442 </div>3435 </div>
3436 <div id="prompt_post_porcessing_form" data-source="custom,openrouter">
3437 <h4 data-i18n="Prompt Post-Processing">Prompt Post-Processing</h4>
3438 <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.">
3439 <option data-i18n="prompt_post_processing_none" value="">None</option>
3440 <option data-i18n="prompt_post_processing_merge" value="merge">Merge consecutive roles</option>
3441 <option data-i18n="prompt_post_processing_semi" value="semi">Semi-strict (alternating roles)</option>
3442 <option data-i18n="prompt_post_processing_strict" value="strict">Strict (user first, alternating roles)</option>
3443 </select>
3444 </div>
3443 <div class="flex-container flex">3445 <div class="flex-container flex">
3444 <div id="api_button_openai" class="api_button menu_button menu_button_icon" type="submit" data-i18n="Connect">Connect</div>3446 <div id="api_button_openai" class="api_button menu_button menu_button_icon" type="submit" data-i18n="Connect">Connect</div>
3445 <div class="api_loading menu_button menu_button_icon" data-i18n="Cancel">Cancel</div>3447 <div class="api_loading menu_button menu_button_icon" data-i18n="Cancel">Cancel</div>
public/scripts/openai.js+1 -1
@@ -2020,6 +2020,7 @@ async function sendOpenAIRequest(type, messages, signal) {
2020 'reasoning_effort': String(oai_settings.reasoning_effort),2020 'reasoning_effort': String(oai_settings.reasoning_effort),
2021 'enable_web_search': Boolean(oai_settings.enable_web_search),2021 'enable_web_search': Boolean(oai_settings.enable_web_search),
2022 'request_images': Boolean(oai_settings.request_images),2022 'request_images': Boolean(oai_settings.request_images),
2023 'custom_prompt_post_processing': oai_settings.custom_prompt_post_processing,
2023 };2024 };
20242025
2025 if (!canMultiSwipe && ToolManager.canPerformToolCalls(type)) {2026 if (!canMultiSwipe && ToolManager.canPerformToolCalls(type)) {
@@ -2100,7 +2101,6 @@ async function sendOpenAIRequest(type, messages, signal) {
2100 generate_data['custom_include_body'] = oai_settings.custom_include_body;2101 generate_data['custom_include_body'] = oai_settings.custom_include_body;
2101 generate_data['custom_exclude_body'] = oai_settings.custom_exclude_body;2102 generate_data['custom_exclude_body'] = oai_settings.custom_exclude_body;
2102 generate_data['custom_include_headers'] = oai_settings.custom_include_headers;2103 generate_data['custom_include_headers'] = oai_settings.custom_include_headers;
2103 generate_data['custom_prompt_post_processing'] = oai_settings.custom_prompt_post_processing;
2104 }2104 }
21052105
2106 if (isCohere) {2106 if (isCohere) {
src/endpoints/backends/chat-completions.js+9 -8
@@ -1048,6 +1048,15 @@ router.post('/generate', function (request, response) {
1048 let bodyParams;1048 let bodyParams;
1049 const isTextCompletion = Boolean(request.body.model && TEXT_COMPLETION_MODELS.includes(request.body.model)) || typeof request.body.messages === 'string';1049 const isTextCompletion = Boolean(request.body.model && TEXT_COMPLETION_MODELS.includes(request.body.model)) || typeof request.body.messages === 'string';
10501050
1051 const postProcessTypes = [CHAT_COMPLETION_SOURCES.CUSTOM, CHAT_COMPLETION_SOURCES.OPENROUTER];
1052 if (Array.isArray(request.body.messages) && postProcessTypes.includes(request.body.chat_completion_source) && request.body.custom_prompt_post_processing) {
1053 console.info('Applying custom prompt post-processing of type', request.body.custom_prompt_post_processing);
1054 request.body.messages = postProcessPrompt(
1055 request.body.messages,
1056 request.body.custom_prompt_post_processing,
1057 getPromptNames(request));
1058 }
1059
1051 if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {1060 if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.OPENAI) {
1052 apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString();1061 apiUrl = new URL(request.body.reverse_proxy || API_OPENAI).toString();
1053 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI);1062 apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.OPENAI);
@@ -1121,14 +1130,6 @@ router.post('/generate', function (request, response) {
11211130
1122 mergeObjectWithYaml(bodyParams, request.body.custom_include_body);1131 mergeObjectWithYaml(bodyParams, request.body.custom_include_body);
1123 mergeObjectWithYaml(headers, request.body.custom_include_headers);1132 mergeObjectWithYaml(headers, request.body.custom_include_headers);
1124
1125 if (request.body.custom_prompt_post_processing) {
1126 console.info('Applying custom prompt post-processing of type', request.body.custom_prompt_post_processing);
1127 request.body.messages = postProcessPrompt(
1128 request.body.messages,
1129 request.body.custom_prompt_post_processing,
1130 getPromptNames(request));
1131 }
1132 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.PERPLEXITY) {1133 } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.PERPLEXITY) {
1133 apiUrl = API_PERPLEXITY;1134 apiUrl = API_PERPLEXITY;
1134 apiKey = readSecret(request.user.directories, SECRET_KEYS.PERPLEXITY);1135 apiKey = readSecret(request.user.directories, SECRET_KEYS.PERPLEXITY);