Merge pull request #2291 from Yokayo/staging

Localizable prompt manager
This commit is contained in:
Cohee
2024-05-24 22:32:04 +03:00
committed by GitHub
9 changed files with 86 additions and 74 deletions

View File

@@ -19,7 +19,7 @@
#completion_prompt_manager #completion_prompt_manager_list li {
display: grid;
grid-template-columns: 4fr 80px 40px;
grid-template-columns: 4fr 80px 45px;
margin-bottom: 0.5em;
width: 100%
}

View File

@@ -1750,13 +1750,13 @@
</div>
</label>
<div class="flex-container flexFlowColumn wide100p textAlignCenter marginTop10" data-source="openai,custom">
<label for="openai_inline_image_quality">
<label for="openai_inline_image_quality" data-i18n="Inline Image Quality">
Inline Image Quality
</label>
<select id="openai_inline_image_quality">
<option value="auto">Auto</option>
<option value="low">Low</option>
<option value="high">High</option>
<option data-i18n="openai_inline_image_quality_auto" value="auto">Auto</option>
<option data-i18n="openai_inline_image_quality_low" value="low">Low</option>
<option data-i18n="openai_inline_image_quality_high" value="high">High</option>
</select>
</div>
</div>
@@ -4511,8 +4511,8 @@
</div>
</div>
<a id="chartokenwarning" class="right_menu_button fa-solid fa-triangle-exclamation" href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#character-tokens" target="_blank" title="About Token 'Limits'"></a>
<i title="Click for stats!" class="fa-solid fa-ranking-star right_menu_button rm_stats_button"></i>
<i title="Toggle character info panel" id="hideCharPanelAvatarButton" class="fa-solid fa-eye right_menu_button"></i>
<i title="Click for stats!" data-i18n="[title]Click for stats!" class="fa-solid fa-ranking-star right_menu_button rm_stats_button"></i>
<i title="Toggle character info panel" data-i18n="[title]Toggle character info panel" id="hideCharPanelAvatarButton" class="fa-solid fa-eye right_menu_button"></i>
</div>
</div>
</div>

View File

@@ -381,7 +381,7 @@
"Delete": "Удалить",
"Cancel": "Отменить",
"Advanced Defininitions": "Расширенное описание",
"Personality summary": "Сводка по личности",
"Personality summary": "Резюме по личности",
"A brief description of the personality": "Краткое описание личности",
"Scenario": "Сценарий",
"Circumstances and context of the dialogue": "Обстоятельства и контекст диалога",
@@ -627,7 +627,7 @@
"Most chats": "Больше всего чатов",
"Least chats": "Меньше всего чатов",
"Back": "Назад",
"Prompt Overrides": "Индивидуальный промпт",
"Prompt Overrides": "Индивидуальные промпты",
"(For OpenAI/Claude/Scale APIs, Window/OpenRouter, and Instruct Mode)": "(для API OpenAI/Claude/Scale, Window/OpenRouter, а также режима Instruct)",
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Введите {{original}} в любое поле, чтобы вставить соответствующий промпт из системных настроек",
"Main Prompt": "Основной промпт",
@@ -872,7 +872,7 @@
"Assistant Prefill": "Префилл для ассистента",
"Start Claude's answer with...": "Начать ответ Клода с...",
"Use system prompt (Claude 2.1+ only)": "Использовать системный промпт (только Claude 2.1+)",
"Send the system prompt for supported models. If disabled, the user message is added to the beginning of the prompt.": "Отправлять системный промпт для поддерживаемых моделей. Если отключено, сообщение пользователя добавляется в начало промпта.",
"Send the system prompt for supported models. If disabled, the user message is added to the beginning of the prompt.": "Отправлять системный промпт для поддерживаемых моделей. Если отключено, в начало промпта добавляется сообщение пользователя.",
"Prompts": "Промпты",
"Total Tokens:": "Всего токенов:",
"Insert prompt": "Вставить промпт",
@@ -1273,5 +1273,15 @@
"To change your user avatar, use the buttons below or select a default persona in the Persona Management menu.": "Чтобы сменить аватарку, используйте кнопки ниже, либо выберите персону по умолчанию в меню управления персоной.",
"These characters are the winners of character design contests and have outstandable quality.": "Персонажи наивысшего качества, одержавшие победу в конкурсе персонажей.",
"Featured Characters": "Рекомендуемые персонажи",
"These characters are the finalists of character design contests and have remarkable quality.": "Персонажи отличного качества, финалисты конкурса персонажей."
"These characters are the finalists of character design contests and have remarkable quality.": "Персонажи отличного качества, финалисты конкурса персонажей.",
"Inline Image Quality": "Качество inline-изображений",
"openai_inline_image_quality_auto": "Автоопределение",
"openai_inline_image_quality_low": "Низкое",
"openai_inline_image_quality_high": "Высокое",
"Assistant Impersonation Prefill": "Префилл для ассистента при перевоплощении",
"Hide Chat Avatars": "Не показывать аватарки в чате",
"Hide avatars in chat messages.": "Скрыть аватарки сбоку от сообщений в чате",
"Flat": "Стандартный",
"Toggle character info panel": "Показать / скрыть инфо-панель",
"(For Chat Completion and Instruct Mode)": "(для Chat Completion и режима Instruct)"
}

View File

@@ -6,6 +6,7 @@ import { Message, TokenHandler } from './openai.js';
import { power_user } from './power-user.js';
import { debounce, waitUntilCondition, escapeHtml } from './utils.js';
import { debounce_timeout } from './constants.js';
import { renderTemplateAsync } from './templates.js';
function debouncePromise(func, delay) {
let timeoutId;
@@ -250,7 +251,7 @@ class PromptManager {
this.error = null;
/** Dry-run for generate, must return a promise */
this.tryGenerate = () => { };
this.tryGenerate = async () => { };
/** Called to persist the configuration, must return a promise */
this.saveServiceSettings = () => { };
@@ -695,23 +696,23 @@ class PromptManager {
if ('character' === this.configuration.promptOrder.strategy && null === this.activeCharacter) return;
this.error = null;
waitUntilCondition(() => !is_send_press && !is_group_generating, 1024 * 1024, 100).then(() => {
waitUntilCondition(() => !is_send_press && !is_group_generating, 1024 * 1024, 100).then(async () => {
if (true === afterTryGenerate) {
// Executed during dry-run for determining context composition
this.profileStart('filling context');
this.tryGenerate().finally(() => {
this.tryGenerate().finally(async () => {
this.profileEnd('filling context');
this.profileStart('render');
this.renderPromptManager();
this.renderPromptManagerListItems();
await this.renderPromptManager();
await this.renderPromptManagerListItems();
this.makeDraggable();
this.profileEnd('render');
});
} else {
// Executed during live communication
this.profileStart('render');
this.renderPromptManager();
this.renderPromptManagerListItems();
await this.renderPromptManager();
await this.renderPromptManagerListItems();
this.makeDraggable();
this.profileEnd('render');
}
@@ -1338,7 +1339,7 @@ class PromptManager {
/**
* Empties, then re-assembles the container containing the prompt list.
*/
renderPromptManager() {
async renderPromptManager() {
let selectedPromptIndex = 0;
const existingAppendSelect = document.getElementById(`${this.configuration.prefix}prompt_manager_footer_append_prompt`);
if (existingAppendSelect instanceof HTMLSelectElement) {
@@ -1349,24 +1350,14 @@ class PromptManager {
const errorDiv = `
<div class="${this.configuration.prefix}prompt_manager_error">
<span class="fa-solid tooltip fa-triangle-exclamation text_danger"></span> ${this.error}
<span class="fa-solid tooltip fa-triangle-exclamation text_danger"></span> ${DOMPurify.sanitize(this.error)}
</div>
`;
const totalActiveTokens = this.tokenUsage;
promptManagerDiv.insertAdjacentHTML('beforeend', `
<div class="range-block">
${this.error ? errorDiv : ''}
<div class="${this.configuration.prefix}prompt_manager_header">
<div class="${this.configuration.prefix}prompt_manager_header_advanced">
<span data-i18n="Prompts">Prompts</span>
</div>
<div>Total Tokens: ${totalActiveTokens} </div>
</div>
<ul id="${this.configuration.prefix}prompt_manager_list" class="text_pole"></ul>
</div>
`);
const headerHtml = await renderTemplateAsync('promptManagerHeader', { error: this.error, errorDiv, prefix: this.configuration.prefix, totalActiveTokens });
promptManagerDiv.insertAdjacentHTML('beforeend', headerHtml);
this.listElement = promptManagerDiv.querySelector(`#${this.configuration.prefix}prompt_manager_list`);
@@ -1384,22 +1375,9 @@ class PromptManager {
selectedPromptIndex = 0;
}
const footerHtml = `
<div class="${this.configuration.prefix}prompt_manager_footer">
<select id="${this.configuration.prefix}prompt_manager_footer_append_prompt" class="text_pole" name="append-prompt">
${promptsHtml}
</select>
<a class="menu_button fa-chain fa-solid" title="Insert prompt" data-i18n="[title]Insert prompt"></a>
<a class="caution menu_button fa-x fa-solid" title="Delete prompt" data-i18n="[title]Delete prompt"></a>
<a class="menu_button fa-file-import fa-solid" id="prompt-manager-import" title="Import a prompt list" data-i18n="[title]Import a prompt list"></a>
<a class="menu_button fa-file-export fa-solid" id="prompt-manager-export" title="Export this prompt list" data-i18n="[title]Export this prompt list"></a>
<a class="menu_button fa-undo fa-solid" id="prompt-manager-reset-character" title="Reset current character" data-i18n="[title]Reset current character"></a>
<a class="menu_button fa-plus-square fa-solid" title="New prompt" data-i18n="[title]New prompt"></a>
</div>
`;
const rangeBlockDiv = promptManagerDiv.querySelector('.range-block');
const headerDiv = promptManagerDiv.querySelector('.completion_prompt_manager_header');
const footerHtml = await renderTemplateAsync('promptManagerFooter', { promptsHtml, prefix: this.configuration.prefix });
headerDiv.insertAdjacentHTML('afterend', footerHtml);
rangeBlockDiv.querySelector('#prompt-manager-reset-character').addEventListener('click', this.handleCharacterReset);
@@ -1410,23 +1388,9 @@ class PromptManager {
footerDiv.querySelector('select').selectedIndex = selectedPromptIndex;
// Add prompt export dialogue and options
const exportForCharacter = `
<div class="row">
<a class="export-promptmanager-prompts-character list-group-item" data-i18n="Export for character">Export for character</a>
<span class="tooltip fa-solid fa-info-circle" title="Export prompts for this character, including their order."></span>
</div>`;
const exportPopup = `
<div id="prompt-manager-export-format-popup" class="list-group">
<div class="prompt-manager-export-format-popup-flex">
<div class="row">
<a class="export-promptmanager-prompts-full list-group-item" data-i18n="Export all">Export all</a>
<span class="tooltip fa-solid fa-info-circle" title="Export all your prompts to a file"></span>
</div>
${'global' === this.configuration.promptOrder.strategy ? '' : exportForCharacter}
</div>
</div>
`;
const exportForCharacter = await renderTemplateAsync('promptManagerExportForCharacter');
const exportPopup = await renderTemplateAsync('promptManagerExportPopup', { isGlobalStrategy: 'global' === this.configuration.promptOrder.strategy, exportForCharacter });
rangeBlockDiv.insertAdjacentHTML('beforeend', exportPopup);
// Destroy previous popper instance if it exists
@@ -1460,7 +1424,7 @@ class PromptManager {
/**
* Empties, then re-assembles the prompt list
*/
renderPromptManagerListItems() {
async renderPromptManagerListItems() {
if (!this.serviceSettings.prompts) return;
const promptManagerList = this.listElement;
@@ -1468,16 +1432,7 @@ class PromptManager {
const { prefix } = this.configuration;
let listItemHtml = `
<li class="${prefix}prompt_manager_list_head">
<span data-i18n="Name">Name</span>
<span></span>
<span class="prompt_manager_prompt_tokens" data-i18n="Tokens">Tokens</span>
</li>
<li class="${prefix}prompt_manager_list_separator">
<hr>
</li>
`;
let listItemHtml = await renderTemplateAsync('promptManagerListHeader', { prefix });
this.getPromptsForCharacter(this.activeCharacter).forEach(prompt => {
if (!prompt) return;
@@ -1602,7 +1557,7 @@ class PromptManager {
data: data,
};
const serializedObject = JSON.stringify(promptExport);
const serializedObject = JSON.stringify(promptExport, null, 4);
const blob = new Blob([serializedObject], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const downloadLink = document.createElement('a');

View File

@@ -0,0 +1,4 @@
<div class="row">
<a class="export-promptmanager-prompts-character list-group-item" data-i18n="Export for character">Export for character</a>
<span class="tooltip fa-solid fa-info-circle" data-i18n="[title]Export prompts for this character, including their order." title="Export prompts for this character, including their order."></span>
</div>

View File

@@ -0,0 +1,12 @@
<div id="prompt-manager-export-format-popup" class="list-group">
<div class="prompt-manager-export-format-popup-flex">
<div class="row">
<a class="export-promptmanager-prompts-full list-group-item" data-i18n="Export all">Export all</a>
<span class="tooltip fa-solid fa-info-circle" data-i18n="[title]Export all your prompts to a file" title="Export all your prompts to a file"></span>
</div>
{{#if isGlobalStrategy}}
{{else}}
{{{exportForCharacter}}}
{{/if}}
</div>
</div>

View File

@@ -0,0 +1,11 @@
<div class="{{prefix}}prompt_manager_footer">
<select id="{{prefix}}prompt_manager_footer_append_prompt" class="text_pole" name="append-prompt">
{{{promptsHtml}}}
</select>
<a class="menu_button fa-chain fa-solid" title="Insert prompt" data-i18n="[title]Insert prompt"></a>
<a class="caution menu_button fa-x fa-solid" title="Delete prompt" data-i18n="[title]Delete prompt"></a>
<a class="menu_button fa-file-import fa-solid" id="prompt-manager-import" title="Import a prompt list" data-i18n="[title]Import a prompt list"></a>
<a class="menu_button fa-file-export fa-solid" id="prompt-manager-export" title="Export this prompt list" data-i18n="[title]Export this prompt list"></a>
<a class="menu_button fa-undo fa-solid" id="prompt-manager-reset-character" title="Reset current character" data-i18n="[title]Reset current character"></a>
<a class="menu_button fa-plus-square fa-solid" title="New prompt" data-i18n="[title]New prompt"></a>
</div>

View File

@@ -0,0 +1,12 @@
<div class="range-block">
{{#if error}}
{{{errorDiv}}}
{{/if}}
<div class="{{prefix}}prompt_manager_header">
<div class="{{prefix}}prompt_manager_header_advanced">
<span data-i18n="Prompts">Prompts</span>
</div>
<div><span data-i18n="Total Tokens:">Total Tokens:</span> {{totalActiveTokens}} </div>
</div>
<ul id="{{prefix}}prompt_manager_list" class="text_pole"></ul>
</div>

View File

@@ -0,0 +1,8 @@
<li class="{{prefix}}prompt_manager_list_head">
<span data-i18n="Name">Name</span>
<span></span>
<span class="prompt_manager_prompt_tokens" data-i18n="Tokens;prompt_manager_tokens">Tokens</span>
</li>
<li class="{{prefix}}prompt_manager_list_separator">
<hr>
</li>