From dec4a7d31e6565380ca249a771009c25ae6c3f15 Mon Sep 17 00:00:00 2001 From: Sevenyine <65720409+Sevenyine@users.noreply.github.com> Date: Wed, 1 Jan 2025 21:45:18 +0800 Subject: [PATCH 01/22] add i18n keys and zh-CN translations --- public/index.html | 6 ++-- public/locales/zh-cn.json | 65 +++++++++++++++++++++++++++++++-------- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/public/index.html b/public/index.html index 41975c4f4..1b2937e0c 100644 --- a/public/index.html +++ b/public/index.html @@ -5962,7 +5962,7 @@
- +
@@ -5975,7 +5975,7 @@
- +
@@ -5988,7 +5988,7 @@
- +
diff --git a/public/locales/zh-cn.json b/public/locales/zh-cn.json index 73ae62b8a..12632b88b 100644 --- a/public/locales/zh-cn.json +++ b/public/locales/zh-cn.json @@ -266,6 +266,8 @@ "Use system prompt": "使用系统提示词", "Merges_all_system_messages_desc_1": "合并所有系统消息,直到第一条具有非系统角色的消息,然后通过", "Merges_all_system_messages_desc_2": "字段发送。", + "Show model thoughts": "展示思维链", + "Display the model's internal thoughts in the response.": "展示模型在回复时的内部思维链。", "Assistant Prefill": "AI预填", "Expand the editor": "展开编辑器", "Start Claude's answer with...": "以如下内容开始Claude的回答...", @@ -430,6 +432,8 @@ "Groq Model": "Groq 模型", "NanoGPT API Key": "NanoGPT API Key", "NanoGPT Model": "NanoGPT Model", + "DeepSeek API Key": "DeepSeek API 密钥", + "DeepSeek Model": "DeepSeek 模型", "Perplexity API Key": "Perplexity API 密钥", "Perplexity Model": "Perplexity 模型", "Cohere API Key": "Cohere API 密钥", @@ -442,11 +446,14 @@ "Custom API Key": "自定义 API 密钥", "(Optional)": "(可选)", "Enter a Model ID": "输入模型名", - "Example: gpt-3.5-turbo": "例如:gpt-3.5-turbo", + "Example: gpt-3.5-turbo": "例如:gpt-4o", "Available Models": "可用模型", "Prompt Post-Processing": "提示词后处理", "Applies additional processing to the prompt before sending it to the API.": "在将提示词发送到 API 之前对其进行额外处理。", "prompt_post_processing_none": "未选择", + "prompt_post_processing_merge": "合并相同角色连续的发言", + "prompt_post_processing_semi": "半严格(强制对话角色交替)", + "prompt_post_processing_strict": "严格(强制对话角色交替、用户最先)", "01.AI API Key": "01.AI API密钥", "01.AI Model": "01.AI 模型", "Additional Parameters": "附加参数", @@ -939,7 +946,7 @@ "Group reply strategy": "群聊回复策略", "Manual": "手动", "Natural order": "自然顺序", - "List order": "上下顺序", + "List order": "从上到下", "Group generation handling mode": "群组生成处理模式", "Swap character cards": "交换角色卡", "Join character cards (exclude muted)": "加入角色卡(不包括被禁言的)", @@ -1112,7 +1119,7 @@ "Cooldown": "冷却", "Entries with a delay can't be activated until there are N messages present in the chat.": "直到聊天中出现 N 条消息时,延迟的条目才能被激活。", "Delay": "延迟", - "Filter to Characters or Tags": "应用到角色或标签", + "Filter to Characters or Tags": "绑定到角色或标签", "Switch the Character/Tags filter around to exclude the listed characters and tags from matching for this entry": "切换角色/标签筛选方式,将列出的角色和标签排除在匹配范围之外", "Exclude": "排除", "-- Characters not found --": "-- 未找到角色 --", @@ -1658,9 +1665,9 @@ "Enable for files": "为文件启用", "Translate files into English before processing": "处理之前将文件翻译成英文", "Message attachments": "消息附件", - "Size threshold (KB)": "大小阈值 (KB)", + "Size threshold (KB)": "大小阈值(KB)", "Chunk size (chars)": "块大小(字符)", - "Chunk overlap (%)": "块重叠 (%)", + "Chunk overlap (%)": "块重叠(%)", "Retrieve chunks": "检索块", "Data Bank files": "数据库文件", "Injection Template": "注入模板", @@ -1691,6 +1698,7 @@ "This will create a new subfolder...": "这将在 /data/ 目录中创建一个新的子文件夹,以用户的句柄作为文件夹名称。", "Note:": "提示:", "this chat is temporary and will be deleted as soon as you leave it.": "此聊天会话是临时的,会在你离开时被删除。", + "Enter a new display name:": "输入一个新的昵称:", "Current Password:": "当前密码:", "New Password:": "新密码:", "Confirm New Password:": "确认新密码:", @@ -1712,13 +1720,16 @@ "chat_rename_2": "注意!!使用已有文件名会导致错误!!", "chat_rename_3": "此举会将次聊天与标记为“检查点”的聊天解绑。", "chat_rename_4": "不需要在结尾添加 '.jsonl'", + "Enter Checkpoint Name:": "输入检查点名称:", + "(Leave empty to auto-generate)": "(留空以自动生成)", + "The currently existing checkpoint will be unlinked and replaced with the new checkpoint, but can still be found in the Chat Management.": "当前检查点将会被解绑并替换为新的检查点,但仍可在聊天管理中找到。", "Include Body Parameters": "包括主体参数", "custom_include_body_desc": "聊天完成请求主体中要包含的参数(YAML 对象)\n\n示例:\n- top_k:20\n- repetition_penalty:1.1", "Exclude Body Parameters": "排除主体参数", "custom_exclude_body_desc": "要从聊天完成请求主体中排除的参数(YAML 数组)\n\n示例:\n- frequency_penalty\n- presence_penalty", "Include Request Headers": "包含请求标头", "custom_include_headers_desc": "聊天完成请求的附加标头(YAML 对象)\n\n示例:\n- CustomHeader:自定义值\n- AnotherHeader:自定义值", - "Debug Warning": "此类别中的功能仅供高级用户使用。如果您不确定后果,请不要点击任何内容。", + "Functions in this category are for advanced users only. Don't click anything if you're not sure about the consequences.": "此类别中的功能仅供高级用户使用。如果您不确定后果,请不要点击任何内容。", "THIS IS PERMANENT!": "此操作不可逆!", "Also delete the chat files": "同时删除聊天文件", "Are you sure you want to delete this user?": "您确定要删除该用户吗?", @@ -1764,11 +1775,11 @@ "help_format_26": "内联代码", "help_format_27": "> 文本", "help_format_28": "显示为块引用(请注意 > 后面的空格)", - "help_format_29": "# 文本", + "help_format_29": "# 文本", "help_format_30": "显示为大标题(注意空格)", - "help_format_32": "## 文本", + "help_format_32": "## 文本", "help_format_33": "显示为中等标题(注意空格)", - "help_format_35": "### 文本", + "help_format_35": "### 文本", "help_format_36": "显示为小标题(注意空格)", "help_1": "您好!请选择您想要详细了解的帮助主题:", "help_2": "斜线命令", @@ -1821,9 +1832,27 @@ "char_import_8": "RisuRealm 角色(直链)", "Supports importing multiple characters.": "支持导入多个角色。", "Write each URL or ID into a new line.": "将每个 URL 或 ID 写入新行。", - "Show Raw Prompt": "显示原始提示", - "Copy Prompt": "复制提示", - "Show Prompt Differences": "显示提示差异", + "Enter the Git URL of the extension to install": "输入扩展程序的 Git URL 以安装", + "Disclaimer:": "免责声明:", + "Please be aware that using external extensions can have unintended side effects and may pose security risks. Always make sure you trust the source before importing an extension. We are not responsible for any damage caused by third-party extensions.": "使用外部的扩展程序可能存在意料外的副作用和安全隐患。在导入扩展程序前,请一定确认其来源可信。我们不为第三方扩展程序造成的任何损失负责。", + "Prompt Itemization": "将提示词分条", + "Show Raw Prompt": "显示原始提示词", + "Copy Prompt": "复制提示词", + "Show Prompt Differences": "显示提示词差异", + "API/Model:": "API/模型:", + "Preset:": "预设:", + "Tokenizer:": "分词器:", + "Only the white numbers really matter. All numbers are estimates. Grey color items may not have been included in the context due to certain prompt format settings.": "只有白色的数字作数。所有数字均为估算。\n 灰色的数字可能因特定的提示词处理规则而被排除在外。", + "System Info:": "系统信息:", + "Prompt Tokens:": "提示词Token:", + "World Info:": "世界书:", + "Chat History:": "聊天记录:", + "Extensions:": "扩展程序:", + "Bias:": "Bias:", + "Total Tokens in Prompt:": "提示词的总Token数量:", + "Max Context": "最大上下文:", + "(Context Size - Response Length)": "(上下文长度 - 回复长度)", + ":": ":", "System-wide Replacement Macros (in order of evaluation):": "系统范围的替换宏(按评估顺序):", "help_macros_1": "仅适用于斜线命令批处理。替换为上一个命令的返回结果。", "help_macros_2": "仅插入一个换行符。", @@ -1913,7 +1942,9 @@ "help_macros_68": "替换为全局变量“name”的值减 1 的结果", "help_macros_69": "替换为范围变量“name”的值", "help_macros_70": "用范围变量“name”的索引处的项目值(对于数组/列表或对象/字典)替换", - "{{name}}": "{{name}}", + "Choose what to export": "选择您想要导出什么:", + "{{name}}": "{{名字}}", + "Choose what to import": "选择您想要导入什么:", "If necessary, you can later restore this chat file from the /backups folder": "若需要,您可稍后在 /backups 文件夹中恢复此聊天文件。", "Also delete the current chat file": "同时删除当前聊天文件", "PErsona Lorebook for": "Persona Lorebook for", @@ -1938,8 +1969,13 @@ "If you have sufficient credits, please try again later.": "若您有足够的余额,请稍后再试。", "Are you sure you want to reset your settings to factory defaults?": "您确定要将您的设置重置为出厂默认设置吗?", "Don't forget to save a snapshot of your settings before proceeding.": "在继续之前,不要忘记保存您的设置快照。", + "Enter your password below to confirm:": "输入您的密码以确认:", "Chat Scenario Override": "聊天场景覆盖", "Remove": "移除", + "Unique to this chat.": "Unique to this chat.", + "All group members will use the following scenario text instead of what is specified in their character cards.": "All group members will use the following scenario text instead of what is specified in their character cards.", + "The following scenario text will be used instead of the value set in the character card.": "The following scenario text will be used instead of the value set in the character card.", + "Checkpoints inherit the scenario override from their parent, and can be changed individually after that.": "Checkpoints inherit the scenario override from their parent, and can be changed individually after that.", "Settings Snapshots": "设置快照", "Record a snapshot of your current settings.": "记录当前设置的快照。", "Make a Snapshot": "制作快照", @@ -1962,6 +1998,7 @@ "Click on the folder icon to use this tag as a folder.": "点击文件夹图标来将此标签作为一个文件夹。", "Use alphabetical sorting": "按字母顺序排列", "tags_sorting_desc": "启用后,标签在创建或重命名时会自动按字母顺序排序。\n禁用后,新标签会追加到末尾。\n\n如果通过拖动手动重新排列标签,则自动排序将被禁用。", + "Are you sure you want to delete the theme?": "你确定要删除这个主题吗?", "Hi,": "嗨,", "To enable multi-account features, restart the SillyTavern server with": "要启用多帐户功能,请使用以下命令重新启动 SillyTavern 服务器", "set to true in the config.yaml file.": "在 config.yaml 文件中设置为 true。", @@ -1982,6 +2019,8 @@ "Reset Settings": "重置设置", "Wipe all user data and reset your account to factory settings.": "删除所有用户数据并将您的账号重置为默认设置。", "Reset Everything": "重置一切", + "This will delete all your settings and data. There will be no undo button. Make sure you have a backup before proceeding.": "This will delete all your settings and data. There will be no undo button.\n Make sure you have a backup before proceeding.", + "Account reset code has been posted to the server console.": "Account reset code has been posted to the server console.", "Reset Code:": "重置代码:", "Want to update?": "获取最新版本", "How to start chatting?": "如何快速开始聊天?", From ee6eb5572d3f869346c63cf25247261af8edb525 Mon Sep 17 00:00:00 2001 From: Sevenyine <65720409+Sevenyine@users.noreply.github.com> Date: Wed, 1 Jan 2025 21:55:03 +0800 Subject: [PATCH 02/22] add translations --- public/locales/zh-cn.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/public/locales/zh-cn.json b/public/locales/zh-cn.json index 12632b88b..4e0e54537 100644 --- a/public/locales/zh-cn.json +++ b/public/locales/zh-cn.json @@ -1114,11 +1114,14 @@ "A relative likelihood of entry activation within the group": "组内进入激活的相对可能性", "Group Weight": "组权重", "Sticky entries will stay active for N messages after being triggered.": "粘性条目在被触发后将保持活跃状态​​ N 条消息。", - "Sticky": "粘性", + "Sticky": "黏性", + "Non-sticky": "无黏性", "Entries with a cooldown can't be activated N messages after being triggered.": "具有冷却时间的条目在触发后 N 条消息内无法被激活。", "Cooldown": "冷却", + "No cooldown": "无冷却", "Entries with a delay can't be activated until there are N messages present in the chat.": "直到聊天中出现 N 条消息时,延迟的条目才能被激活。", "Delay": "延迟", + "No delay": "无延迟", "Filter to Characters or Tags": "绑定到角色或标签", "Switch the Character/Tags filter around to exclude the listed characters and tags from matching for this entry": "切换角色/标签筛选方式,将列出的角色和标签排除在匹配范围之外", "Exclude": "排除", From 0bda86c35260ead168db6cc48a50071d7f55fdb9 Mon Sep 17 00:00:00 2001 From: Sevenyine <65720409+Sevenyine@users.noreply.github.com> Date: Sat, 4 Jan 2025 18:09:12 +0800 Subject: [PATCH 03/22] Supplemented zh-CN UI translation --- public/index.html | 2 +- public/locales/ru-ru.json | 2 +- public/locales/zh-cn.json | 78 +++++++++++++++++++-------------------- public/locales/zh-tw.json | 2 +- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/public/index.html b/public/index.html index 1b2937e0c..daa5e0964 100644 --- a/public/index.html +++ b/public/index.html @@ -3319,7 +3319,7 @@

Enter a Model ID

- +

Available Models

diff --git a/public/locales/ru-ru.json b/public/locales/ru-ru.json index 5c506a88b..4c8ae8282 100644 --- a/public/locales/ru-ru.json +++ b/public/locales/ru-ru.json @@ -1132,7 +1132,7 @@ "Custom API Key": "Ключ от кастомного API", "(Optional)": "(необязательно)", "Enter a Model ID": "Введите идентификатор модели", - "Example: gpt-3.5-turbo": "Пример: gpt-3.5-turbo", + "Example: gpt-4o": "Пример: gpt-4o", "Available Models": "Доступные модели", "Prompt Post-Processing": "Постобработка промпта", "Applies additional processing to the prompt before sending it to the API.": "Позволяет обработать промпт перед отправкой в API.", diff --git a/public/locales/zh-cn.json b/public/locales/zh-cn.json index 4e0e54537..6c199ccaf 100644 --- a/public/locales/zh-cn.json +++ b/public/locales/zh-cn.json @@ -185,13 +185,13 @@ "Mirostat Eta": "Mirostat η", "Learning rate of Mirostat": "Mirostat 的学习率。", "Beam search": "束搜索", - "A greedy, brute-force algorithm used in LLM sampling to find the most likely sequence of words or tokens. It expands multiple candidate sequences at once, maintaining a fixed number (beam width) of top sequences at each step.": "A greedy, brute-force algorithm used in LLM sampling to find the most likely sequence of words or tokens. It expands multiple candidate sequences at once, maintaining a fixed number (beam width) of top sequences at each step.", - "# of Beams": "# of Beams", + "A greedy, brute-force algorithm used in LLM sampling to find the most likely sequence of words or tokens. It expands multiple candidate sequences at once, maintaining a fixed number (beam width) of top sequences at each step.": "一种在LLM采样中使用的贪婪暴力算法,用于找到最可能的单词或标记序列。它一次扩展多个候选序列,在每一步保留固定数量(光束宽度)的最佳序列。", + "# of Beams": "光束数量", "The number of sequences generated at each step with Beam Search.": "The number of sequences generated at each step with Beam Search.", "Length Penalty": "长度惩罚", "Penalize sequences based on their length.": "Penalize sequences based on their length.", "Early Stopping": "提前停止", - "Controls the stopping condition for beam search. If checked, the generation stops as soon as there are '# of Beams' sequences. If not checked, a heuristic is applied and the generation is stopped when it's very unlikely to find better candidates.": "Controls the stopping condition for beam search. If checked, the generation stops as soon as there are '# of Beams' sequences. If not checked, a heuristic is applied and the generation is stopped when it's very unlikely to find better candidates.", + "Controls the stopping condition for beam search. If checked, the generation stops as soon as there are '# of Beams' sequences. If not checked, a heuristic is applied and the generation is stopped when it's very unlikely to find better candidates.": "控制光束搜索的停止条件。勾选时,当生成到达‘光束数量’的序列时停止。如果未勾选,则采用启发式方法,当几乎不可能找到更好的候选项时停止生成。", "Contrastive search": "对比搜索", "Contrastive_search_txt": "通过利用大多数 LLM 表示空间的各向同性以鼓励多样性同时保持一致性的采样器。详见 Su 等人在 2022 年发表的论文 《A Contrastive Framework for Neural Text Generation》。", "Penalty Alpha": "惩罚系数 α", @@ -208,7 +208,7 @@ "Speculative Ngram": "推测性 Ngram", "Use a different speculative decoding method without a draft model": "使用不同的推测解码方法(不采用草稿模型)。最好使用草稿模型。推测性 Ngram 的效果不太好。", "Spaces Between Special Tokens": "特殊词符之间的空格", - "Seed_desc": "A random seed to use for deterministic and reproducable outputs. Set to -1 to use a random seed.", + "Seed_desc": "一个用于生成确定性和可复现的输出的随机种子。设置为 -1 时会使用随机种子。", "LLaMA / Mistral / Yi models only": "LLaMA / Mistral / Yi模型专用。首先确保您选择了适当的词符化器。\n这项设置决定了你不想在结果中看到的字符串。\n每行一个字符串。可以是文本或者[词符id]。\n许多词符以空格开头。如果不确定,请使用词符计数器。", "Example: some text [42, 69, 1337]": "例如:\n一些文本\n[42, 69, 1337]", "CFG": "CFG", @@ -227,8 +227,8 @@ "llama.cpp only. Determines the order of samplers. If Mirostat mode is not 0, sampler order is ignored.": "仅限 llama.cpp。确定采样器的顺序。如果 Mirostat 模式不为 0,则忽略采样器顺序。", "Sampler Priority": "采样器优先级", "Ooba only. Determines the order of samplers.": "确定采样器的顺序(仅适用于Ooba)", - "Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.": "Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.", - "Aphrodite only. Determines the order of samplers.": "Aphrodite only. Determines the order of samplers.", + "Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.": "仅适用于 Aphrodite,用于确定采样器的顺序。偏移(Skew)始终在 softmax 后应用,因此不包含在这里。", + "Aphrodite only. Determines the order of samplers.": "仅适用于 Aphrodite。用于确定采样器的顺序。", "Character Names Behavior": "角色名称行为", "Helps the model to associate messages with characters.": "有助于模型将消息与角色关联起来。", "None": "无", @@ -274,7 +274,7 @@ "Assistant Impersonation Prefill": "AI帮答预填", "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.": "为支持的模型发送系统提示词。如果禁用,则用户消息将添加到提示词的开头。", - "Confirm token parsing with": "Confirm token parsing with", + "Confirm token parsing with": "确认使用以下工具进行词符解析", "Tokenizer": "词符化器", "New preset": "新预设", "Delete preset": "删除预设", @@ -320,7 +320,7 @@ "Novel AI Model": "Novel AI 模型", "No connection...": "没有连接...", "API Type": "API 类型", - "Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]": "Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]", + "Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]": "通用(兼容 OpenAI)[LM Studio、LiteLLM 等]", "TogetherAI API Key": "TogetherAI API 密钥", "TogetherAI Model": "TogetherAI 模型", "-- Connect to the API --": "-- 连接到API --", @@ -352,7 +352,7 @@ "All": "All", "class": "All Classes", "Toggle grid view": "切换网格视图", - "No model description": "[No description]", + "No model description": "[无描述]", "vllm-project/vllm": "vllm-project/vllm(OpenAI API 包装器模式)", "vLLM API key": "vLLM API 密钥", "Example: 127.0.0.1:8000": "示例:http://127.0.0.1:8000", @@ -401,12 +401,12 @@ "View API Usage Metrics": "查看API使用情况", "Follow": "按照", "these directions": "这些步骤", - "to get your OpenAI API key.": "获取您的OpenAI API密钥。", + "to get your OpenAI API key.": "获取您的 OpenAI API 密钥。", "Use Proxy password field instead. This input will be ignored.": "请使用“代理密码”字段。此输入将被忽略。", "OpenAI Model": "OpenAI 模型", "Bypass API status check": "绕过API状态检查", "Show External models (provided by API)": "显示外部模型(由API提供)", - "Claude API Key": "Claude API Key", + "Claude API Key": "Claude API 密钥", "Get your key from": "从以下位置获取您的密钥", "Anthropic's developer console": "Anthropic 开发者控制台", "Claude Model": "Claude 模型", @@ -438,15 +438,15 @@ "Perplexity Model": "Perplexity 模型", "Cohere API Key": "Cohere API 密钥", "Cohere Model": "Cohere 模型", - "Block Entropy API Key": "Block Entropy API Key", - "Select a Model": "Select a Model", - "Custom Endpoint (Base URL)": "自定义端点(基本 URL)", + "Block Entropy API Key": "Block Entropy API 密钥", + "Select a Model": "选择一个模型", + "Custom Endpoint (Base URL)": "自定义端点(基础 URL)", "Example: http://localhost:1234/v1": "例如:http://localhost:1234/v1", "at the end of the URL!": "到 URL 的末尾!", "Custom API Key": "自定义 API 密钥", "(Optional)": "(可选)", "Enter a Model ID": "输入模型名", - "Example: gpt-3.5-turbo": "例如:gpt-4o", + "Example: gpt-4o": "例如:gpt-4o", "Available Models": "可用模型", "Prompt Post-Processing": "提示词后处理", "Applies additional processing to the prompt before sending it to the API.": "在将提示词发送到 API 之前对其进行额外处理。", @@ -510,25 +510,25 @@ "Never": "永不", "Groups and Past Personas": "Groups and Past Personas", "Always": "永远", - "Instruct Sequences": "Instruct Sequences", - "User Message Sequences": "User Message Sequences", + "Instruct Sequences": "指令序列", + "User Message Sequences": "用户消息序列", "Inserted before a User message and as a last prompt line when impersonating.": "插入到用户消息之前并作为模拟时的最后一行提示词。", "User Prefix": "用户消息前缀", "Inserted after a User message.": "插入到用户消息之后。", "User Suffix": "用户消息后缀", - "Assistant Message Sequences": "Assistant Message Sequences", + "Assistant Message Sequences": "助手消息序列", "Inserted before an Assistant message and as a last prompt line when generating an AI reply.": "插入到助手消息之前并作为生成 AI 回复时的最后一行提示词。", "Assistant Prefix": "助手消息前缀", "Inserted after an Assistant message.": "插入于助手消息之后。", "Assistant Suffix": "助手消息后缀", - "System Message Sequences": "System Message Sequences", + "System Message Sequences": "系统消息序列", "Inserted before a System (added by slash commands or extensions) message.": "插入到系统(由快捷命令或扩展添加)消息之前。", - "System Prefix": "System Message Prefix", + "System Prefix": "系统消息前缀", "Inserted after a System message.": "插入到系统消息之后。", - "System Suffix": "System Message Suffix", + "System Suffix": "系统消息后缀", "If enabled, System Sequences will be the same as User Sequences.": "如果启用,系统序列将与用户序列相同。", "System same as User": "系统与用户相同", - "System Prompt Sequences": "System Prompt Sequences", + "System Prompt Sequences": "系统提示词序列", "Inserted before a System prompt.": "插入到系统提示词之前。", "System Prompt Prefix": "系统提示词前缀", "Inserted after a System prompt.": "在系统提示词后插入。", @@ -563,7 +563,7 @@ "Token Padding": "词符填充", "Miscellaneous": "杂项", "Non-markdown strings": "非 Markdown 字符串", - "comma delimited,no spaces between": "comma delimited,no spaces between", + "comma delimited,no spaces between": "以逗号分隔,无需空格", "Start Reply With": "以...开始回复", "Show reply prefix in chat": "在聊天中显示回复前缀", "World Info": "世界信息", @@ -695,8 +695,8 @@ "Show Message Token Count": "显示消息词符数", "Single-row message input area. Mobile only, no effect on PC": "将输入框限制为一行。仅适用于移动设备,对PC无影响", "Compact Input Area (Mobile)": "紧凑输入区域(移动端)", - "Display swipe numbers for all messages, not just the last.": "Display swipe numbers for all messages, not just the last.", - "Swipe # for All Messages": "Swipe # for All Messages", + "Display swipe numbers for all messages, not just the last.": "显示所有信息的滑动编号,而非仅限最后一条。", + "Swipe # for All Messages": "给所有信息分配滑动编号 #", "In the Character Management panel, show quick selection buttons for favorited characters": "在角色管理面板中,显示快速选择按钮以选择收藏的角色", "Characters Hotswap": "角色卡热切换", "Enable magnification for zoomed avatar display.": "启用放大功能以放大头像显示。", @@ -901,7 +901,7 @@ "Favorite characters to add them to HotSwaps": "收藏角色以将它们添加到快速热切换区", "Token counts may be inaccurate and provided just for reference.": "词符计数可能不准确,仅供参考。", "Total tokens": "总词符数", - "Calculating...": "正在计算…", + "Calculating...": "正在计算...", "Tokens": "词符数", "Permanent tokens": "永久词符", "Permanent": "恒定的", @@ -1030,7 +1030,7 @@ "Chatty": "高", "Examples of dialogue": "对话示例", "Important to set the character's writing style.": "设置角色的写作风格,很重要!", - "(Examples of chat dialog. Begin each example with START on a new line.)": "(聊天对话的示例,每个示例都另起一行以开头。)", + "(Examples of chat dialog. Begin each example with START on a new line.)": "(聊天对话的示例,每个示例都另起一行以开头。)", "Save": "保存", "Chat History": "聊天记录", "Import Chat": "导入聊天", @@ -1142,8 +1142,8 @@ "prompt_manager_relative": "相对", "prompt_manager_in_chat": "聊天中", "prompt_manager_depth": "深度", - "Injection depth. 0 = after the last message, 1 = before the last message, etc.": "注入深度。0 = 在最后一条消息之后,1 = 在最后一条消息之前,等等。", - "The content of this prompt is pulled from elsewhere and cannot be edited here.": "The content of this prompt is pulled from elsewhere and cannot be edited here.", + "Injection depth. 0 = after the last message, 1 = before the last message, etc.": "注入深度。“0”为在最后一条消息之后,“1”为在最后一条消息之前,等等。", + "The content of this prompt is pulled from elsewhere and cannot be edited here.": "此提示词的内容是从其他地方提取的,无法在此处进行编辑。", "Prompt": "提示词", "The prompt to be sent.": "要发送的提示词。", "This prompt cannot be overridden by character cards, even if overrides are preferred.": "即使选择覆盖,此提示词也不能被角色卡覆盖。", @@ -1204,7 +1204,7 @@ "alternate_greetings_hint_1": "点击", "alternate_greetings_hint_2": "按钮即可开始!", "Alternate Greeting #": "额外问候语 #", - "(This will be the first message from the character that starts every chat)": "(这是每次聊天开始时角色的第一条消息)", + "(This will be the first message from the character that starts every chat)": "(这是每次聊天开始时角色的第一条消息)", "View contents": "查看内容", "Remove the file": "删除文件", "Author's Note": "作者注释", @@ -1217,7 +1217,7 @@ "Insertion Frequency": "插入频率", "(0 = Disable, 1 = Always)": "(“0”为禁用,“1”为始终)", "User inputs until next insertion:": "用户输入直到下一次插入:", - "Character Author's Note (Private)": "人物作者注(私有)", + "Character Author's Note (Private)": "人物作者注(私密)", "Won't be shared with the character card on export.": "导出时不会与角色卡共享。", "Will be automatically added as the author's note for this character. Will be used in groups, but can't be modified when a group chat is open.": "会自动添加为该角色的作者注解,在群聊中使用,但群聊开启时无法修改。", "Use character author's note": "使用角色作者的注释", @@ -1244,9 +1244,9 @@ "Insertion Depth:": "插入深度:", "Token Probabilities": "词符概率", "Select a token to see alternatives considered by the AI.": "选择一个词符来查看 AI 考虑的替代方案。", - "Reroll with the entire prefix": "Reroll with the entire prefix", + "Reroll with the entire prefix": "使用完整前缀重新生成", "Not connected to API!": "未连接到API!", - "Type a message, or /? for help": "键入消息,或 /? 获取帮助", + "Type a message, or /? for help": "输入想发送的消息,或输入 /? 获取帮助", "Continue script execution": "继续执行脚本", "Pause script execution": "暂停执行脚本", "Abort script execution": "中止执行脚本", @@ -1365,7 +1365,7 @@ "You are in offline mode. Click on the image below to set the expression.": "您处于离线模式。点击下方图片即可设置表情。", "Sprite Folder Override": "表情文件夹覆盖", "Use a forward slash to specify a subfolder. Example: _space": "使用正斜杠指定子文件夹。例如:", - "Upload sprite pack (ZIP)": "上传表情包 (ZIP)", + "Upload sprite pack (ZIP)": "上传表情包(ZIP)", "Remove all image overrides": "删除所有图片覆盖", "Create new folder in the _space": "创建新文件夹到", "folder of your user data directory and name it as the name of the character.": "用户数据目录的文件夹并将其命名为角色的名称。", @@ -1576,7 +1576,7 @@ "Click to set": "点击设置", "You can find your API key in the Stability AI dashboard.": "您可以在 Stability AI 仪表板中找到您的 API 密钥。", "Style Preset": "风格预设", - "Prompt Upsampling": "Prompt Upsampling", + "Prompt Upsampling": "提示词增强(Upsampling)", "Sampling method": "采样方法", "Scheduler": "调度器", "Resolution": "分辨率", @@ -1637,9 +1637,9 @@ "Select TTS Provider": "选择 文本转语音 的服务提供商", "tts_enabled": "已启用", "Narrate user messages": "朗读用户消息", - "Auto Generation": "Auto Generation", - "Requires auto generation to be enabled.": "Requires auto generation to be enabled.", - "Narrate by paragraphs (when streaming)": "Narrate by paragraphs (when streaming)", + "Auto Generation": "自动生成", + "Requires auto generation to be enabled.": "需要启用自动生成功能。", + "Narrate by paragraphs (when streaming)": "按段朗读(流式播放时)", "Only narrate quotes": "只朗读引号内文本", "Ignore text, even quotes, inside asterisk": "不朗读所有*星号内文本*,即使其被引号包裹", "Narrate only the translated text": "只朗读翻译后文本", @@ -1946,7 +1946,7 @@ "help_macros_69": "替换为范围变量“name”的值", "help_macros_70": "用范围变量“name”的索引处的项目值(对于数组/列表或对象/字典)替换", "Choose what to export": "选择您想要导出什么:", - "{{name}}": "{{名字}}", + "{{name}}": "{{name}}", "Choose what to import": "选择您想要导入什么:", "If necessary, you can later restore this chat file from the /backups folder": "若需要,您可稍后在 /backups 文件夹中恢复此聊天文件。", "Also delete the current chat file": "同时删除当前聊天文件", diff --git a/public/locales/zh-tw.json b/public/locales/zh-tw.json index 51ad1df08..56e2c34e8 100644 --- a/public/locales/zh-tw.json +++ b/public/locales/zh-tw.json @@ -1453,7 +1453,7 @@ "Any contents here will replace the default Post-History Instructions used for this character. (v2 specpost_history_instructions)": "此處填入的內容將取代該角色的默認聊天歷史後指示(Post-History Instructions)。\n(v2 格式:specpost_history_instructions)", "comma delimited,no spaces between": "逗號分割,無需空格", "e.g. black-forest-labs/FLUX.1-dev": "例如:black-forest-labs/FLUX.1-dev", - "Example: gpt-3.5-turbo": "例如:gpt-3.5-turbo", + "Example: gpt-4o": "例如:gpt-4o", "Example: http://localhost:1234/v1": "例如:http://localhost:1234/v1", "popup-button-crop": "裁剪", "(disabled when max recursion steps are used)": "(當最大遞歸步驟數使用時將停用)", From efa80267f61ad75e83a4e3621a547c0951771c84 Mon Sep 17 00:00:00 2001 From: Sevenyine <65720409+Sevenyine@users.noreply.github.com> Date: Sun, 5 Jan 2025 10:19:55 +0800 Subject: [PATCH 04/22] Update --- public/locales/zh-cn.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/locales/zh-cn.json b/public/locales/zh-cn.json index 6c199ccaf..6a3fefae1 100644 --- a/public/locales/zh-cn.json +++ b/public/locales/zh-cn.json @@ -943,7 +943,7 @@ "Chat Name (Optional)": "聊天名称(可选)", "Chat Lore": "聊天知识", "Click to select a new avatar for this group": "单击选择该群聊的新头像", - "Group reply strategy": "群聊回复策略", + "Group reply strategy": "群聊发言顺序", "Manual": "手动", "Natural order": "自然顺序", "List order": "从上到下", @@ -1594,7 +1594,7 @@ "Karras": "Karras", "Not all samplers supported.": "并非所有采样器都受支持。", "sd_adetailer_face": "Use ADetailer with face model during the generation. The ADetailer extension must be installed on the backend.", - "Use ADetailer (Face)": "使用 ADetailer (Face)", + "Use ADetailer (Face)": "使用 ADetailer(脸部)", "SMEA versions of samplers are modified to perform better at high resolution.": "SMEA 版本的采样器经过修改,在高分辨率下性能更佳。", "SMEA": "中小企业协会", "DYN variants of SMEA samplers often lead to more varied output, but may fail at very high resolutions.": "SMEA 采样器的 DYN 变体通常会产生更加多样化的输出,但在非常高的分辨率下可能会失败。", @@ -1722,7 +1722,7 @@ "chat_rename_1": "输入聊天的新名称:", "chat_rename_2": "注意!!使用已有文件名会导致错误!!", "chat_rename_3": "此举会将次聊天与标记为“检查点”的聊天解绑。", - "chat_rename_4": "不需要在结尾添加 '.jsonl'", + "chat_rename_4": "不需要在结尾添加 '.JSONL'", "Enter Checkpoint Name:": "输入检查点名称:", "(Leave empty to auto-generate)": "(留空以自动生成)", "The currently existing checkpoint will be unlinked and replaced with the new checkpoint, but can still be found in the Chat Management.": "当前检查点将会被解绑并替换为新的检查点,但仍可在聊天管理中找到。", From 7f5ce54b1f7b8e017f2b38b78584bf75481c86c1 Mon Sep 17 00:00:00 2001 From: zerofata Date: Sat, 11 Jan 2025 11:32:05 +1300 Subject: [PATCH 05/22] Add returnChunks and resultSize args to /db-search --- public/scripts/extensions/vectors/index.js | 32 ++++++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/public/scripts/extensions/vectors/index.js b/public/scripts/extensions/vectors/index.js index 36b910f06..2bf8a7144 100644 --- a/public/scripts/extensions/vectors/index.js +++ b/public/scripts/extensions/vectors/index.js @@ -1613,25 +1613,39 @@ jQuery(async () => { callback: async (args, query) => { const clamp = (v) => Number.isNaN(v) ? null : Math.min(1, Math.max(0, v)); const threshold = clamp(Number(args?.threshold ?? settings.score_threshold)); + const validateSize = (v) => Number.isNaN(v) || !Number.isInteger(v) || v < 1 ? null : v; + const resultSize = validateSize(Number(args?.resultSize)) ?? settings.chunk_count_db; const source = String(args?.source ?? ''); const attachments = source ? getDataBankAttachmentsForSource(source, false) : getDataBankAttachments(false); const collectionIds = await ingestDataBankAttachments(String(source)); - const queryResults = await queryMultipleCollections(collectionIds, String(query), settings.chunk_count_db, threshold); + const queryResults = await queryMultipleCollections(collectionIds, String(query), resultSize, threshold); + const returnChunks = String(args?.returnChunks).toLowerCase() === 'true' + + if (returnChunks) { + let textResult = ''; + for (const collectionId in queryResults) { + const metadata = queryResults[collectionId].metadata?.filter(x => x.text)?.sort((a, b) => a.index - b.index)?.map(x => x.text)?.filter(onlyUnique) || []; + textResult += metadata.join('\n') + '\n\n'; + } + return textResult; + } else { + // Map collection IDs to file URLs + const urls = Object + .keys(queryResults) + .map(x => attachments.find(y => getFileCollectionId(y.url) === x)) + .filter(x => x) + .map(x => x.url); - // Map collection IDs to file URLs - const urls = Object - .keys(queryResults) - .map(x => attachments.find(y => getFileCollectionId(y.url) === x)) - .filter(x => x) - .map(x => x.url); - - return JSON.stringify(urls); + return JSON.stringify(urls); + } }, aliases: ['databank-search', 'data-bank-search'], helpString: 'Search the Data Bank for a specific query using vector similarity. Returns a list of file URLs with the most relevant content.', namedArgumentList: [ new SlashCommandNamedArgument('threshold', 'Threshold for the similarity score in the [0, 1] range. Uses the global config value if not set.', ARGUMENT_TYPE.NUMBER, false, false, ''), + new SlashCommandNamedArgument('resultSize', 'Maximum number of query results to return.', ARGUMENT_TYPE.NUMBER, false, false, ''), new SlashCommandNamedArgument('source', 'Optional filter for the attachments by source.', ARGUMENT_TYPE.STRING, false, false, '', ['global', 'character', 'chat']), + new SlashCommandNamedArgument('returnChunks', 'If true, returns the actual content chunks instead of URLs.', ARGUMENT_TYPE.STRING, false, false, '', ['true', 'false']), ], unnamedArgumentList: [ new SlashCommandArgument('Query to search by.', ARGUMENT_TYPE.STRING, true, false), From 4c1c62a56b1c9aff1d1a2d8a5a548866d546d119 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Sat, 11 Jan 2025 01:41:46 +0100 Subject: [PATCH 06/22] Add QR set rename button --- .../extensions/quick-reply/html/settings.html | 1 + .../quick-reply/src/ui/SettingsUi.js | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/public/scripts/extensions/quick-reply/html/settings.html b/public/scripts/extensions/quick-reply/html/settings.html index a9a810fd8..3c8100aae 100644 --- a/public/scripts/extensions/quick-reply/html/settings.html +++ b/public/scripts/extensions/quick-reply/html/settings.html @@ -46,6 +46,7 @@
Edit Quick Replies
+ diff --git a/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js b/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js index 920c2cd30..e655a73f2 100644 --- a/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js +++ b/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js @@ -111,6 +111,7 @@ export class SettingsUi { prepareQrEditor() { // qr editor + this.dom.querySelector('#qr--set-rename').addEventListener('click', async () => this.renameQrSet()); this.dom.querySelector('#qr--set-new').addEventListener('click', async()=>this.addQrSet()); /**@type {HTMLInputElement}*/ const importFile = this.dom.querySelector('#qr--set-importFile'); @@ -303,6 +304,44 @@ export class SettingsUi { this.settings.save(); } + async renameQrSet() { + const newName = await callPopup('Enter new name for the Quick Reply Set:', 'input'); + if (newName && newName.length > 0) { + const existingSet = QuickReplySet.get(newName); + if (existingSet) { + toastr.error(`A Quick Reply Set named "${newName}" already exists.`); + return; + } + const oldName = this.currentQrSet.name; + this.currentQrSet.name = newName; + await this.currentQrSet.save(); + + // Update the option in all select dropdowns + /** @type {NodeListOf} */ + const options = this.dom.querySelectorAll(`#qr--set option[value="${oldName}"], select.qr--set option[value="${oldName}"]`); + options.forEach(option => { + option.value = newName; + option.textContent = newName; + }); + + // Update in in both set lists + this.settings.config.setList.forEach(set => { + if (set.set.name === oldName) { + set.set.name = newName; + } + }); + this.settings.chatConfig?.setList.forEach(set => { + if (set.set.name === oldName) { + set.set.name = newName; + } + }); + + this.settings.save(); + this.currentSet.value = newName; + console.info(`Quick Reply Set renamed from ""${oldName}" to "${newName}".`); + } + } + async addQrSet() { const name = await callPopup('Quick Reply Set Name:', 'input'); if (name && name.length > 0) { From 0f45ebda0376fc26173dae6f36784aced52fe132 Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Sat, 11 Jan 2025 01:59:38 +0100 Subject: [PATCH 07/22] Refactor QR set popups to new popup --- .../extensions/quick-reply/src/ui/SettingsUi.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js b/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js index e655a73f2..de7bc0d7f 100644 --- a/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js +++ b/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js @@ -1,4 +1,4 @@ -import { callPopup } from '../../../../../script.js'; +import { Popup } from '../../../../popup.js'; import { getSortableDelay } from '../../../../utils.js'; import { log, warn } from '../../index.js'; import { QuickReply } from '../QuickReply.js'; @@ -280,7 +280,7 @@ export class SettingsUi { } async deleteQrSet() { - const confirmed = await callPopup(`Are you sure you want to delete the Quick Reply Set "${this.currentQrSet.name}"?
This cannot be undone.`, 'confirm'); + const confirmed = await Popup.show.confirm('Delete Quick Reply Set', `Are you sure you want to delete the Quick Reply Set "${this.currentQrSet.name}"?
This cannot be undone.`); if (confirmed) { await this.doDeleteQrSet(this.currentQrSet); this.rerender(); @@ -305,7 +305,7 @@ export class SettingsUi { } async renameQrSet() { - const newName = await callPopup('Enter new name for the Quick Reply Set:', 'input'); + const newName = await Popup.show.input('Rename Quick Reply Set', 'Enter a new name:', this.currentQrSet.name); if (newName && newName.length > 0) { const existingSet = QuickReplySet.get(newName); if (existingSet) { @@ -343,11 +343,11 @@ export class SettingsUi { } async addQrSet() { - const name = await callPopup('Quick Reply Set Name:', 'input'); + const name = await Popup.show.input('Create a new World Info', 'Enter a name for the new Quick Reply Set:'); if (name && name.length > 0) { const oldQrs = QuickReplySet.get(name); if (oldQrs) { - const replace = await callPopup(`A Quick Reply Set named "${name}" already exists.
Do you want to overwrite the existing Quick Reply Set?
The existing set will be deleted. This cannot be undone.`, 'confirm'); + const replace = Popup.show.confirm('Replace existing World Info', `A Quick Reply Set named "${name}" already exists.
Do you want to overwrite the existing Quick Reply Set?
The existing set will be deleted. This cannot be undone.`); if (replace) { const idx = QuickReplySet.list.indexOf(oldQrs); await this.doDeleteQrSet(oldQrs); @@ -408,7 +408,7 @@ export class SettingsUi { qrs.init(); const oldQrs = QuickReplySet.get(props.name); if (oldQrs) { - const replace = await callPopup(`A Quick Reply Set named "${qrs.name}" already exists.
Do you want to overwrite the existing Quick Reply Set?
The existing set will be deleted. This cannot be undone.`, 'confirm'); + const replace = Popup.show.confirm('Replace existing World Info', `A Quick Reply Set named "${name}" already exists.
Do you want to overwrite the existing Quick Reply Set?
The existing set will be deleted. This cannot be undone.`); if (replace) { const idx = QuickReplySet.list.indexOf(oldQrs); await this.doDeleteQrSet(oldQrs); From 3455da404ac735e94110d57ce11fd102f39dc25f Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Sat, 11 Jan 2025 02:22:10 +0100 Subject: [PATCH 08/22] Add QR set duplicate button --- .../extensions/quick-reply/html/settings.html | 1 + .../quick-reply/src/ui/SettingsUi.js | 37 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/public/scripts/extensions/quick-reply/html/settings.html b/public/scripts/extensions/quick-reply/html/settings.html index 3c8100aae..210ad4f32 100644 --- a/public/scripts/extensions/quick-reply/html/settings.html +++ b/public/scripts/extensions/quick-reply/html/settings.html @@ -51,6 +51,7 @@ +
diff --git a/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js b/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js index de7bc0d7f..419275b92 100644 --- a/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js +++ b/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js @@ -120,7 +120,8 @@ export class SettingsUi { importFile.value = null; }); this.dom.querySelector('#qr--set-import').addEventListener('click', ()=>importFile.click()); - this.dom.querySelector('#qr--set-export').addEventListener('click', async()=>this.exportQrSet()); + this.dom.querySelector('#qr--set-export').addEventListener('click', async () => this.exportQrSet()); + this.dom.querySelector('#qr--set-duplicate').addEventListener('click', async () => this.duplicateQrSet()); this.dom.querySelector('#qr--set-delete').addEventListener('click', async()=>this.deleteQrSet()); this.dom.querySelector('#qr--set-add').addEventListener('click', async()=>{ this.currentQrSet.addQuickReply(); @@ -460,6 +461,40 @@ export class SettingsUi { URL.revokeObjectURL(url); } + async duplicateQrSet() { + const newName = await Popup.show.input('Duplicate Quick Reply Set', 'Enter a name for the new Quick Reply Set:', `${this.currentQrSet.name} (Copy)`); + if (newName && newName.length > 0) { + const existingSet = QuickReplySet.get(newName); + if (existingSet) { + toastr.error(`A Quick Reply Set named "${newName}" already exists.`); + return; + } + const newQrSet = QuickReplySet.from(JSON.parse(JSON.stringify(this.currentQrSet))); + newQrSet.name = newName; + newQrSet.qrList = this.currentQrSet.qrList.map(qr => QuickReply.from(JSON.parse(JSON.stringify(qr)))); + newQrSet.addQuickReply(); + const idx = QuickReplySet.list.findIndex(it => it.name.toLowerCase().localeCompare(newName.toLowerCase()) == 1); + if (idx > -1) { + QuickReplySet.list.splice(idx, 0, newQrSet); + } else { + QuickReplySet.list.push(newQrSet); + } + const opt = document.createElement('option'); { + opt.value = newQrSet.name; + opt.textContent = newQrSet.name; + if (idx > -1) { + this.currentSet.children[idx].insertAdjacentElement('beforebegin', opt); + } else { + this.currentSet.append(opt); + } + } + this.currentSet.value = newName; + this.onQrSetChange(); + this.prepareGlobalSetList(); + this.prepareChatSetList(); + } + } + selectQrSet(qrs) { this.currentSet.value = qrs.name; this.onQrSetChange(); From b89d41a70145bcf1ca6dc47d3dd00a21667b3ffe Mon Sep 17 00:00:00 2001 From: Wolfsblvt Date: Sat, 11 Jan 2025 02:31:14 +0100 Subject: [PATCH 09/22] Refactor prepare/redraw for consistency --- .../quick-reply/src/ui/SettingsUi.js | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js b/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js index 419275b92..df6bb081f 100644 --- a/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js +++ b/public/scripts/extensions/quick-reply/src/ui/SettingsUi.js @@ -317,15 +317,7 @@ export class SettingsUi { this.currentQrSet.name = newName; await this.currentQrSet.save(); - // Update the option in all select dropdowns - /** @type {NodeListOf} */ - const options = this.dom.querySelectorAll(`#qr--set option[value="${oldName}"], select.qr--set option[value="${oldName}"]`); - options.forEach(option => { - option.value = newName; - option.textContent = newName; - }); - - // Update in in both set lists + // Update it in both set lists this.settings.config.setList.forEach(set => { if (set.set.name === oldName) { set.set.name = newName; @@ -336,9 +328,19 @@ export class SettingsUi { set.set.name = newName; } }); - this.settings.save(); + + // Update the option in the current selected QR dropdown. All others will be refreshed via the prepare calls below. + /** @type {HTMLOptionElement} */ + const option = this.currentSet.querySelector(`#qr--set option[value="${oldName}"]`); + option.value = newName; + option.textContent = newName; + this.currentSet.value = newName; + this.onQrSetChange(); + this.prepareGlobalSetList(); + this.prepareChatSetList(); + console.info(`Quick Reply Set renamed from ""${oldName}" to "${newName}".`); } } From fc5debc660633ff8b51293c8a39b838919b96cc4 Mon Sep 17 00:00:00 2001 From: zerofata Date: Sat, 11 Jan 2025 17:42:19 +1300 Subject: [PATCH 10/22] replaced returnChunks with return arg to use existing helper functions --- public/scripts/extensions/vectors/index.js | 44 +++++++++++++++------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/public/scripts/extensions/vectors/index.js b/public/scripts/extensions/vectors/index.js index 2bf8a7144..62a8c33fa 100644 --- a/public/scripts/extensions/vectors/index.js +++ b/public/scripts/extensions/vectors/index.js @@ -30,6 +30,8 @@ import { textgen_types, textgenerationwebui_settings } from '../../textgen-setti import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js'; import { SlashCommand } from '../../slash-commands/SlashCommand.js'; import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js'; +import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js'; +import { slashCommandReturnHelper } from '../../slash-commands/SlashCommandReturnHelper.js'; import { callGenericPopup, POPUP_RESULT, POPUP_TYPE } from '../../popup.js'; import { generateWebLlmChatPrompt, isWebLlmSupported } from '../shared.js'; @@ -1619,25 +1621,31 @@ jQuery(async () => { const attachments = source ? getDataBankAttachmentsForSource(source, false) : getDataBankAttachments(false); const collectionIds = await ingestDataBankAttachments(String(source)); const queryResults = await queryMultipleCollections(collectionIds, String(query), resultSize, threshold); - const returnChunks = String(args?.returnChunks).toLowerCase() === 'true' - - if (returnChunks) { + + // Get URLs + const urls = Object + .keys(queryResults) + .map(x => attachments.find(y => getFileCollectionId(y.url) === x)) + .filter(x => x) + .map(x => x.url); + + // Gets the actual text content of chunks + const getChunksText = () => { let textResult = ''; for (const collectionId in queryResults) { const metadata = queryResults[collectionId].metadata?.filter(x => x.text)?.sort((a, b) => a.index - b.index)?.map(x => x.text)?.filter(onlyUnique) || []; textResult += metadata.join('\n') + '\n\n'; } return textResult; - } else { - // Map collection IDs to file URLs - const urls = Object - .keys(queryResults) - .map(x => attachments.find(y => getFileCollectionId(y.url) === x)) - .filter(x => x) - .map(x => x.url); - - return JSON.stringify(urls); + }; + + if (args.return === 'chunks') { + return getChunksText(); } + + // @ts-ignore + return slashCommandReturnHelper.doReturn(args.return ?? 'object', urls, { objectToStringFunc: list => list.join('\n') }); + }, aliases: ['databank-search', 'data-bank-search'], helpString: 'Search the Data Bank for a specific query using vector similarity. Returns a list of file URLs with the most relevant content.', @@ -1645,7 +1653,17 @@ jQuery(async () => { new SlashCommandNamedArgument('threshold', 'Threshold for the similarity score in the [0, 1] range. Uses the global config value if not set.', ARGUMENT_TYPE.NUMBER, false, false, ''), new SlashCommandNamedArgument('resultSize', 'Maximum number of query results to return.', ARGUMENT_TYPE.NUMBER, false, false, ''), new SlashCommandNamedArgument('source', 'Optional filter for the attachments by source.', ARGUMENT_TYPE.STRING, false, false, '', ['global', 'character', 'chat']), - new SlashCommandNamedArgument('returnChunks', 'If true, returns the actual content chunks instead of URLs.', ARGUMENT_TYPE.STRING, false, false, '', ['true', 'false']), + SlashCommandNamedArgument.fromProps({ + name: 'return', + description: 'How you want the return value to be provided', + typeList: [ARGUMENT_TYPE.STRING], + defaultValue: 'object', + enumList: [ + new SlashCommandEnumValue('chunks', 'Return the actual content chunks', enumTypes.enum, '{}'), + ...slashCommandReturnHelper.enumList({ allowObject: true }) + ], + forceEnum: true, + }) ], unnamedArgumentList: [ new SlashCommandArgument('Query to search by.', ARGUMENT_TYPE.STRING, true, false), From 1dccb08cd66bd3f212c04c7509a031beca826ab2 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sat, 11 Jan 2025 19:04:36 +0200 Subject: [PATCH 11/22] Add enumerator for MacrosParser --- public/scripts/macros.js | 31 ++++++++++++++++++- .../slash-commands/SlashCommandParser.js | 4 +++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/public/scripts/macros.js b/public/scripts/macros.js index 3464b7a64..960dad146 100644 --- a/public/scripts/macros.js +++ b/public/scripts/macros.js @@ -26,6 +26,12 @@ Handlebars.registerHelper('helperMissing', function () { * @typedef {(nonce: string) => string} MacroFunction */ +/** + * @typedef {Object} CustomMacro + * @property {string} key - Macro name (key) + * @property {string} description - Optional description of the macro + */ + export class MacrosParser { /** * A map of registered macros. @@ -33,12 +39,29 @@ export class MacrosParser { */ static #macros = new Map(); + /** + * A map of macro descriptions. + * @type {Map} + */ + static #descriptions = new Map(); + + /** + * Returns an iterator over all registered macros. + * @returns {IterableIterator} + */ + static [Symbol.iterator] = function* () { + for (const macro of this.#macros.values()) { + yield { key: macro, description: this.#descriptions.get(macro) }; + } + }; + /** * Registers a global macro that can be used anywhere where substitution is allowed. * @param {string} key Macro name (key) * @param {string|MacroFunction} value A string or a function that returns a string + * @param {string} [description] Optional description of the macro */ - static registerMacro(key, value) { + static registerMacro(key, value, description = '') { if (typeof key !== 'string') { throw new Error('Macro key must be a string'); } @@ -64,6 +87,10 @@ export class MacrosParser { } this.#macros.set(key, value); + + if (typeof description === 'string' && description) { + this.#descriptions.set(key, description); + } } /** @@ -88,6 +115,8 @@ export class MacrosParser { if (!deleted) { console.warn(`Macro ${key} was not registered`); } + + this.#descriptions.delete(key); } /** diff --git a/public/scripts/slash-commands/SlashCommandParser.js b/public/scripts/slash-commands/SlashCommandParser.js index 539757568..aeda79d5a 100644 --- a/public/scripts/slash-commands/SlashCommandParser.js +++ b/public/scripts/slash-commands/SlashCommandParser.js @@ -22,6 +22,7 @@ import { SlashCommandBreakPoint } from './SlashCommandBreakPoint.js'; import { SlashCommandDebugController } from './SlashCommandDebugController.js'; import { commonEnumProviders } from './SlashCommandCommonEnumsProvider.js'; import { SlashCommandBreak } from './SlashCommandBreak.js'; +import { MacrosParser } from '../macros.js'; /** @typedef {import('./SlashCommand.js').NamedArgumentsCapture} NamedArgumentsCapture */ /** @typedef {import('./SlashCommand.js').NamedArguments} NamedArguments */ @@ -494,6 +495,9 @@ export class SlashCommandParser { li.querySelector('tt').textContent, (li.querySelector('tt').remove(),li.innerHTML), )); + for (const macro of MacrosParser) { + options.push(new MacroAutoCompleteOption(macro.name, `{{${macro.name}}}`, macro.description || 'No description provided')); + } const result = new AutoCompleteNameResult( macro.name, macro.start + 2, From 1d5cf8d25c738801b8a922df4a4e290122719733 Mon Sep 17 00:00:00 2001 From: Yokayo Date: Sun, 12 Jan 2025 00:42:58 +0700 Subject: [PATCH 12/22] Work on translation --- public/index.html | 18 +-- public/locales/ru-ru.json | 137 ++++++++++++++++-- public/scripts/extensions.js | 22 +-- .../extensions/connection-manager/edit.html | 4 +- .../connection-manager/profile.html | 4 +- public/scripts/openai.js | 4 +- public/scripts/textgen-models.js | 41 +++--- public/scripts/world-info.js | 35 ++--- 8 files changed, 188 insertions(+), 77 deletions(-) diff --git a/public/index.html b/public/index.html index 57562c9e7..6ea9cef3f 100644 --- a/public/index.html +++ b/public/index.html @@ -2278,7 +2278,7 @@

Model Providers

-