feat:便宜配置文件GUI,可以方便编辑配置文件

This commit is contained in:
SengokuCola
2025-05-29 19:19:41 +08:00
parent 9347f52a4d
commit 56c6252c6c
2 changed files with 1135 additions and 0 deletions

638
scripts/070configexe.py Normal file
View File

@@ -0,0 +1,638 @@
import tkinter as tk
from tkinter import ttk, messagebox
import tomli
import tomli_w
import os
from typing import Any, Dict, List, Union
import threading
import time
class ConfigEditor:
def __init__(self, root):
self.root = root
self.root.title("麦麦配置编辑器")
# 加载编辑器配置
self.load_editor_config()
# 设置窗口大小
self.root.geometry(f"{self.window_width}x{self.window_height}")
# 加载配置
self.load_config()
# 自动保存相关
self.last_save_time = time.time()
self.save_timer = None
self.save_lock = threading.Lock()
self.current_section = None # 当前编辑的节
self.pending_save = False # 是否有待保存的更改
# 存储控件的字典
self.widgets = {}
# 创建主框架
self.main_frame = ttk.Frame(self.root, padding="10")
self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 创建版本号显示
self.create_version_label()
# 创建左侧导航栏
self.create_navbar()
# 创建右侧编辑区
self.create_editor()
# 创建底部按钮
self.create_buttons()
# 配置网格权重
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
self.main_frame.columnconfigure(1, weight=1)
self.main_frame.rowconfigure(1, weight=1) # 修改为1因为第0行是版本号
def load_editor_config(self):
"""加载编辑器配置"""
try:
editor_config_path = os.path.join(os.path.dirname(__file__), "configexe.toml")
with open(editor_config_path, "rb") as f:
self.editor_config = tomli.load(f) # 保存整个配置对象
# 设置配置路径
self.config_path = self.editor_config["config"]["bot_config_path"]
# 如果路径是相对路径,转换为绝对路径
if not os.path.isabs(self.config_path):
self.config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), self.config_path)
# 设置编辑器参数
self.window_width = self.editor_config["editor"]["window_width"]
self.window_height = self.editor_config["editor"]["window_height"]
self.save_delay = self.editor_config["editor"]["save_delay"]
# 加载翻译
self.translations = self.editor_config.get("translations", {})
except Exception as e:
messagebox.showerror("错误", f"加载编辑器配置失败: {str(e)}")
# 使用默认值
self.editor_config = {} # 初始化空配置
self.config_path = "config/bot_config.toml"
self.window_width = 1000
self.window_height = 800
self.save_delay = 1.0
self.translations = {}
def load_config(self):
try:
with open(self.config_path, "rb") as f:
self.config = tomli.load(f)
except Exception as e:
messagebox.showerror("错误", f"加载配置文件失败: {str(e)}")
self.config = {}
def create_version_label(self):
"""创建版本号显示标签"""
version = self.config.get("inner", {}).get("version", "未知版本")
version_frame = ttk.Frame(self.main_frame)
version_frame.grid(row=0, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=(0, 10))
version_label = ttk.Label(version_frame, text=f"麦麦版本:{version}", font=("", 10, "bold"))
version_label.pack(side=tk.LEFT, padx=5)
def create_navbar(self):
# 创建左侧导航栏
self.nav_frame = ttk.Frame(self.main_frame, padding="5")
self.nav_frame.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# 创建导航树
self.tree = ttk.Treeview(self.nav_frame)
self.tree.pack(fill=tk.BOTH, expand=True)
# 添加快捷设置节
self.tree.insert("", "end", text="快捷设置", values=("quick_settings",))
# 添加配置项到树
for section in self.config:
if section != "inner": # 跳过inner部分
# 获取节的中文名称
section_trans = self.translations.get("sections", {}).get(section, {})
section_name = section_trans.get("name", section)
self.tree.insert("", "end", text=section_name, values=(section,))
# 绑定选择事件
self.tree.bind("<<TreeviewSelect>>", self.on_section_select)
def create_editor(self):
# 创建右侧编辑区
self.editor_frame = ttk.Frame(self.main_frame, padding="5")
self.editor_frame.grid(row=1, column=1, sticky=(tk.W, tk.E, tk.N, tk.S))
# 创建编辑区标题
self.editor_title = ttk.Label(self.editor_frame, text="")
self.editor_title.pack(fill=tk.X)
# 创建编辑区内容
self.editor_content = ttk.Frame(self.editor_frame)
self.editor_content.pack(fill=tk.BOTH, expand=True)
# 创建滚动条
self.scrollbar = ttk.Scrollbar(self.editor_content)
self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 创建画布和框架
self.canvas = tk.Canvas(self.editor_content, yscrollcommand=self.scrollbar.set)
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.scrollbar.config(command=self.canvas.yview)
# 创建内容框架
self.content_frame = ttk.Frame(self.canvas)
self.canvas.create_window((0, 0), window=self.content_frame, anchor=tk.NW)
# 绑定画布大小变化事件
self.content_frame.bind("<Configure>", self.on_frame_configure)
self.canvas.bind("<Configure>", self.on_canvas_configure)
def on_frame_configure(self, event=None):
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def on_canvas_configure(self, event):
# 更新内容框架的宽度以适应画布
self.canvas.itemconfig(self.canvas.find_withtag("all")[0], width=event.width)
def create_buttons(self):
# 创建底部按钮区
self.button_frame = ttk.Frame(self.main_frame, padding="5")
self.button_frame.grid(row=2, column=0, columnspan=2, sticky=(tk.W, tk.E))
# 刷新按钮
self.refresh_button = ttk.Button(self.button_frame, text="刷新", command=self.refresh_config)
self.refresh_button.pack(side=tk.RIGHT, padx=5)
def create_widget_for_value(self, parent: ttk.Frame, key: str, value: Any, path: List[str]) -> None:
"""为不同类型的值创建对应的编辑控件"""
frame = ttk.Frame(parent)
frame.pack(fill=tk.X, padx=5, pady=2)
# --- 修改开始: 改进翻译查找逻辑 ---
full_config_path_key = ".".join(path + [key]) # 例如 "chinese_typo.enable"
item_name_to_display = key # 默认显示原始键名
item_desc_to_display = "" # 默认无描述
# 1. 尝试使用完整路径的特定翻译
specific_translation = self.translations.get("items", {}).get(full_config_path_key)
if specific_translation and specific_translation.get("name"):
item_name_to_display = specific_translation.get("name")
item_desc_to_display = specific_translation.get("description", "")
else:
# 2. 如果特定翻译未找到或没有name尝试使用通用键名的翻译
generic_translation = self.translations.get("items", {}).get(key)
if generic_translation and generic_translation.get("name"):
item_name_to_display = generic_translation.get("name")
item_desc_to_display = generic_translation.get("description", "")
# --- 修改结束 ---
# 配置名(大号字体)
label = ttk.Label(frame, text=item_name_to_display, font=("", 20, "bold"))
label.grid(row=0, column=0, sticky=tk.W, padx=5, pady=(0, 0))
# 星星图标快捷设置(与配置名同一行)
content_col_offset_for_star = 1 # 星标按钮占一列
quick_settings = self.editor_config.get("editor", {}).get("quick_settings", {}).get("items", [])
already_in_quick = any(item.get("path") == full_config_path_key for item in quick_settings)
icon = "" if already_in_quick else ""
icon_fg = "#FFD600" # 始终金色
def on_star_click():
self.toggle_quick_setting(full_config_path_key, widget_type, item_name_to_display, item_desc_to_display, already_in_quick)
# 立即刷新本分组
for widget in parent.winfo_children():
widget.destroy()
self.widgets.clear()
# 重新渲染本分组
if hasattr(self, 'current_section') and self.current_section and self.current_section != "quick_settings":
self.create_section_widgets(parent, self.current_section, self.config[self.current_section], [self.current_section])
elif hasattr(self, 'current_section') and self.current_section == "quick_settings":
self.create_quick_settings_widgets() # 如果当前是快捷设置,也刷新它
pin_btn = ttk.Button(frame, text=icon, width=2, command=on_star_click)
pin_btn.grid(row=0, column=content_col_offset_for_star, sticky=tk.W, padx=5)
try:
pin_btn.configure(style="Pin.TButton")
style = ttk.Style()
style.configure("Pin.TButton", foreground=icon_fg)
except Exception:
pass
# 配置项描述(第二行)
desc_row = 1
if item_desc_to_display:
desc_label = ttk.Label(frame, text=item_desc_to_display, foreground="gray", font=("", 16))
desc_label.grid(row=desc_row, column=0, columnspan=content_col_offset_for_star + 1, sticky=tk.W, padx=5, pady=(0, 4))
widget_row = desc_row + 1 # 内容控件在描述下方
else:
widget_row = desc_row # 内容控件直接在第二行
# 配置内容控件(第三行或第二行)
if path[0] == "inner":
value_label = ttk.Label(frame, text=str(value), font=("", 20))
value_label.grid(row=widget_row, column=0, columnspan=content_col_offset_for_star +1, sticky=tk.W, padx=5)
return
if isinstance(value, bool):
# 布尔值使用复选框
var = tk.BooleanVar(value=value)
checkbox = ttk.Checkbutton(frame, variable=var, command=lambda: self.on_value_changed())
checkbox.grid(row=widget_row, column=0, columnspan=content_col_offset_for_star +1, sticky=tk.W, padx=5)
self.widgets[tuple(path + [key])] = var
widget_type = "bool"
elif isinstance(value, (int, float)):
# 数字使用数字输入框
var = tk.StringVar(value=str(value))
entry = ttk.Entry(frame, textvariable=var, font=("", 20))
entry.grid(row=widget_row, column=0, columnspan=content_col_offset_for_star +1, sticky=tk.W+tk.E, padx=5)
var.trace_add("write", lambda *args: self.on_value_changed())
self.widgets[tuple(path + [key])] = var
widget_type = "number"
elif isinstance(value, list):
# 列表使用每行一个输入框的形式
frame_list = ttk.Frame(frame)
frame_list.grid(row=widget_row, column=0, columnspan=content_col_offset_for_star +1, sticky=tk.W+tk.E, padx=5)
# 创建添加和删除按钮
button_frame = ttk.Frame(frame_list)
button_frame.pack(side=tk.RIGHT, padx=5)
add_button = ttk.Button(button_frame, text="+", width=3, command=lambda p=path + [key]: self.add_list_item(frame_list, p))
add_button.pack(side=tk.TOP, pady=2)
# 创建列表项框架
items_frame = ttk.Frame(frame_list)
items_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)
# 存储所有输入框的变量
entry_vars = []
# 为每个列表项创建输入框
for i, item in enumerate(value):
self.create_list_item(items_frame, item, i, entry_vars, path + [key])
# 存储控件引用
self.widgets[tuple(path + [key])] = (items_frame, entry_vars)
widget_type = "list"
else:
# 其他类型(字符串等)使用普通文本框
var = tk.StringVar(value=str(value))
entry = ttk.Entry(frame, textvariable=var, font=("", 20))
entry.grid(row=widget_row, column=0, columnspan=content_col_offset_for_star +1, sticky=tk.W+tk.E, padx=5)
var.trace_add("write", lambda *args: self.on_value_changed())
self.widgets[tuple(path + [key])] = var
widget_type = "text"
def create_section_widgets(self, parent: ttk.Frame, section: str, data: Dict, path=None) -> None:
"""为配置节创建编辑控件"""
if path is None:
path = [section]
# 获取节的中文名称和描述
section_trans = self.translations.get("sections", {}).get(section, {})
section_name = section_trans.get("name", section)
section_desc = section_trans.get("description", "")
# 创建节的标签框架
section_frame = ttk.Frame(parent)
section_frame.pack(fill=tk.X, padx=5, pady=10)
# 创建节的名称标签
section_label = ttk.Label(section_frame, text=f"[{section_name}]", font=("", 12, "bold"))
section_label.pack(side=tk.LEFT, padx=5)
# 创建节的描述标签
if section_desc:
desc_label = ttk.Label(section_frame, text=f"({section_desc})", foreground="gray")
desc_label.pack(side=tk.LEFT, padx=5)
# 为每个配置项创建对应的控件
for key, value in data.items():
if isinstance(value, dict):
self.create_section_widgets(parent, key, value, path + [key])
else:
self.create_widget_for_value(parent, key, value, path)
def on_value_changed(self):
"""当值改变时触发自动保存"""
self.pending_save = True
current_time = time.time()
if current_time - self.last_save_time > self.save_delay:
if self.save_timer:
self.root.after_cancel(self.save_timer)
self.save_timer = self.root.after(int(self.save_delay * 1000), self.save_config)
def on_section_select(self, event):
# 如果有待保存的更改,先保存
if self.pending_save:
self.save_config()
selection = self.tree.selection()
if not selection:
return
section = self.tree.item(selection[0])["values"][0] # 使用values中的原始节名
self.current_section = section
# 获取节的中文名称
if section == "quick_settings":
section_name = "快捷设置"
else:
section_trans = self.translations.get("sections", {}).get(section, {})
section_name = section_trans.get("name", section)
self.editor_title.config(text=f"编辑 {section_name}")
# 清空编辑器
for widget in self.content_frame.winfo_children():
widget.destroy()
# 清空控件字典
self.widgets.clear()
# 创建编辑控件
if section == "quick_settings":
self.create_quick_settings_widgets()
elif section in self.config:
self.create_section_widgets(self.content_frame, section, self.config[section])
def create_quick_settings_widgets(self):
"""创建快捷设置编辑界面"""
# 获取快捷设置配置
quick_settings = self.editor_config.get("editor", {}).get("quick_settings", {}).get("items", [])
# 创建快捷设置控件
for setting in quick_settings:
frame = ttk.Frame(self.content_frame)
frame.pack(fill=tk.X, padx=5, pady=2)
# 获取当前值
path = setting["path"].split(".")
current = self.config
for key in path[:-1]: # 除了最后一个键
current = current.get(key, {})
value = current.get(path[-1]) # 获取最后一个键的值
# 创建名称标签
name_label = ttk.Label(frame, text=setting["name"], font=("", 18))
name_label.pack(fill=tk.X, padx=5, pady=(2, 0))
# 创建描述标签
if setting.get("description"):
desc_label = ttk.Label(frame, text=setting['description'], foreground="gray", font=("", 16))
desc_label.pack(fill=tk.X, padx=5, pady=(0, 2))
# 根据类型创建不同的控件
setting_type = setting.get("type", "bool")
if setting_type == "bool":
value = bool(value) if value is not None else False
var = tk.BooleanVar(value=value)
checkbox = ttk.Checkbutton(frame, text="",
variable=var,
command=lambda p=path, v=var: self.on_quick_setting_changed(p, v))
checkbox.pack(anchor=tk.W, padx=5, pady=(0,5))
elif setting_type == "text":
value = str(value) if value is not None else ""
var = tk.StringVar(value=value)
entry = ttk.Entry(frame, textvariable=var, width=40, font=("", 18))
entry.pack(fill=tk.X, padx=5, pady=(0,5))
var.trace_add("write", lambda *args, p=path, v=var: self.on_quick_setting_changed(p, v))
elif setting_type == "number":
value = str(value) if value is not None else "0"
var = tk.StringVar(value=value)
entry = ttk.Entry(frame, textvariable=var, width=10, font=("", 18))
entry.pack(fill=tk.X, padx=5, pady=(0,5))
var.trace_add("write", lambda *args, p=path, v=var: self.on_quick_setting_changed(p, v))
elif setting_type == "list":
# 对于列表类型,创建一个按钮来打开编辑窗口
button = ttk.Button(frame, text="编辑列表",
command=lambda p=path, s=setting: self.open_list_editor(p, s))
button.pack(anchor=tk.W, padx=5, pady=(0,5))
def create_list_item(self, parent, value, index, entry_vars, path):
"""创建单个列表项的输入框"""
item_frame = ttk.Frame(parent)
item_frame.pack(fill=tk.X, pady=1)
# 创建输入框
var = tk.StringVar(value=str(value))
entry = ttk.Entry(item_frame, textvariable=var)
entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
var.trace_add("write", lambda *args: self.on_value_changed())
# 创建删除按钮
del_button = ttk.Button(item_frame, text="-", width=3,
command=lambda: self.remove_list_item(parent, item_frame, entry_vars, index, path))
del_button.pack(side=tk.RIGHT, padx=5)
# 存储变量引用
entry_vars.append(var)
def add_list_item(self, parent, path):
"""添加新的列表项"""
items_frame = parent.winfo_children()[1] # 获取列表项框架
entry_vars = self.widgets[tuple(path)][1] # 获取变量列表
# 创建新的列表项
self.create_list_item(items_frame, "", len(entry_vars), entry_vars, path)
self.on_value_changed()
def remove_list_item(self, parent, item_frame, entry_vars, index, path):
"""删除列表项"""
item_frame.destroy()
entry_vars.pop(index)
self.on_value_changed()
def get_widget_value(self, widget) -> Any:
"""获取控件的值"""
if isinstance(widget, tk.BooleanVar):
return widget.get()
elif isinstance(widget, tk.StringVar):
value = widget.get()
try:
# 尝试转换为数字
if "." in value:
return float(value)
return int(value)
except ValueError:
return value
elif isinstance(widget, tuple): # 列表类型
items_frame, entry_vars = widget
# 获取所有非空输入框的值
return [var.get() for var in entry_vars if var.get().strip()]
return None
def save_config(self):
"""保存配置到文件"""
if not self.pending_save:
return
with self.save_lock:
try:
# 获取所有控件的值
for path, widget in self.widgets.items():
value = self.get_widget_value(widget)
# 更新配置
current = self.config
for key in path[:-1]:
current = current[key]
final_key = path[-1] # 直接用最后一个key
current[final_key] = value
# 保存到文件
with open(self.config_path, "wb") as f:
tomli_w.dump(self.config, f)
self.last_save_time = time.time()
self.pending_save = False
self.editor_title.config(text=f"{self.editor_title.cget('text')} (已保存)")
self.root.after(2000, lambda: self.editor_title.config(text=self.editor_title.cget('text').replace(" (已保存)", "")))
except Exception as e:
messagebox.showerror("错误", f"保存配置失败: {str(e)}")
def refresh_config(self):
# 如果有待保存的更改,先保存
if self.pending_save:
self.save_config()
self.load_config()
self.tree.delete(*self.tree.get_children())
for section in self.config:
# 获取节的中文名称
section_trans = self.translations.get("sections", {}).get(section, {})
section_name = section_trans.get("name", section)
self.tree.insert("", "end", text=section_name, values=(section,))
messagebox.showinfo("成功", "配置已刷新")
def open_list_editor(self, path, setting):
"""打开列表编辑窗口"""
# 创建新窗口
dialog = tk.Toplevel(self.root)
dialog.title(f"编辑 {setting['name']}")
dialog.geometry("400x300")
# 获取当前值
current = self.config
for key in path[:-1]:
current = current.get(key, {})
value = current.get(path[-1], [])
# 创建编辑区
frame = ttk.Frame(dialog, padding="10")
frame.pack(fill=tk.BOTH, expand=True)
# 创建列表项框架
items_frame = ttk.Frame(frame)
items_frame.pack(fill=tk.BOTH, expand=True)
# 存储所有输入框的变量
entry_vars = []
# 为每个列表项创建输入框
for i, item in enumerate(value):
self.create_list_item(items_frame, item, i, entry_vars, path)
# 创建按钮框架
button_frame = ttk.Frame(frame)
button_frame.pack(fill=tk.X, pady=10)
# 添加按钮
add_button = ttk.Button(button_frame, text="添加",
command=lambda: self.add_list_item(items_frame, path))
add_button.pack(side=tk.LEFT, padx=5)
# 保存按钮
save_button = ttk.Button(button_frame, text="保存",
command=lambda: self.save_list_editor(dialog, path, entry_vars))
save_button.pack(side=tk.RIGHT, padx=5)
def save_list_editor(self, dialog, path, entry_vars):
"""保存列表编辑窗口的内容"""
# 获取所有非空输入框的值
values = [var.get() for var in entry_vars if var.get().strip()]
# 更新配置
current = self.config
for key in path[:-1]:
if key not in current:
current[key] = {}
current = current[key]
current[path[-1]] = values
# 触发保存
self.on_value_changed()
# 关闭窗口
dialog.destroy()
def on_quick_setting_changed(self, path, var):
"""快捷设置值改变时的处理"""
# 更新配置
current = self.config
for key in path[:-1]:
if key not in current:
current[key] = {}
current = current[key]
# 根据变量类型设置值
if isinstance(var, tk.BooleanVar):
current[path[-1]] = var.get()
elif isinstance(var, tk.StringVar):
value = var.get()
try:
# 尝试转换为数字
if "." in value:
current[path[-1]] = float(value)
else:
current[path[-1]] = int(value)
except ValueError:
current[path[-1]] = value
# 触发保存
self.on_value_changed()
def toggle_quick_setting(self, full_path, widget_type, name, desc, already_in_quick):
quick_settings = self.editor_config.setdefault("editor", {}).setdefault("quick_settings", {}).setdefault("items", [])
if already_in_quick:
# 移除
self.editor_config["editor"]["quick_settings"]["items"] = [item for item in quick_settings if item.get("path") != full_path]
else:
# 添加
quick_settings.append({
"name": name,
"description": desc,
"path": full_path,
"type": widget_type
})
# 保存到configexe.toml
import tomli_w, os
config_path = os.path.join(os.path.dirname(__file__), "configexe.toml")
with open(config_path, "wb") as f:
tomli_w.dump(self.editor_config, f)
self.refresh_quick_settings()
def refresh_quick_settings(self):
# 重新渲染快捷设置栏(如果当前在快捷设置页)
if self.current_section == "quick_settings":
for widget in self.content_frame.winfo_children():
widget.destroy()
self.widgets.clear()
self.create_quick_settings_widgets()
def main():
root = tk.Tk()
app = ConfigEditor(root)
root.mainloop()
if __name__ == "__main__":
main()

497
scripts/configexe.toml Normal file
View File

@@ -0,0 +1,497 @@
[config]
bot_config_path = "config/bot_config.toml"
[editor]
window_width = 1000
window_height = 800
save_delay = 1.0
[[editor.quick_settings.items]]
name = "性格细节"
description = "麦麦性格的细节描述条数任意不能为0"
path = "personality.personality_sides"
type = "list"
[[editor.quick_settings.items]]
name = "身份细节"
description = "麦麦的身份特征描述,可以描述外貌、性别、身高、职业、属性等"
path = "identity.identity_detail"
type = "list"
[[editor.quick_settings.items]]
name = "表达风格"
description = "麦麦说话的表达风格,表达习惯"
path = "expression.expression_style"
type = "text"
[[editor.quick_settings.items]]
name = "聊天模式"
description = "麦麦的聊天模式normal普通模式、focus专注模式、auto自动模式"
path = "chat.chat_mode"
type = "text"
[[editor.quick_settings.items]]
name = "退出专注阈值"
description = "自动退出专注聊天的阈值,越低越容易退出专注聊天"
path = "chat.exit_focus_threshold"
type = "number"
[[editor.quick_settings.items]]
name = "偷取表情包"
description = "是否偷取表情包,让麦麦可以发送她保存的这些表情包"
path = "emoji.steal_emoji"
type = "bool"
[[editor.quick_settings.items]]
name = "核心性格"
description = "麦麦的核心性格描述建议50字以内"
path = "personality.personality_core"
type = "text"
[[editor.quick_settings.items]]
name = "自动专注阈值"
description = "自动切换到专注聊天的阈值,越低越容易进入专注聊天"
path = "chat.auto_focus_threshold"
type = "number"
[[editor.quick_settings.items]]
name = "自我识别处理器"
description = "是否启用自我识别处理器"
path = "focus_chat_processor.self_identify_processor"
type = "bool"
[[editor.quick_settings.items]]
name = "工具使用处理器"
description = "是否启用工具使用处理器"
path = "focus_chat_processor.tool_use_processor"
type = "bool"
[[editor.quick_settings.items]]
name = "工作记忆处理器"
description = "是否启用工作记忆处理器,不稳定,消耗量大"
path = "focus_chat_processor.working_memory_processor"
type = "bool"
[translations.sections.inner]
name = "版本"
description = "麦麦的内部配置,包含版本号等信息。此部分仅供显示,不可编辑。"
[translations.sections.bot]
name = "麦麦bot配置"
description = "麦麦的基本配置包括QQ号、昵称和别名等基础信息"
[translations.sections.personality]
name = "人格"
description = "麦麦的性格设定包括核心性格建议50字以内和细节描述"
[translations.sections.identity]
name = "身份特点"
description = "麦麦的身份特征,包括年龄、性别、外貌等描述,可以描述外貌、性别、身高、职业、属性等"
[translations.sections.expression]
name = "表达方式"
description = "麦麦的表达方式和学习设置,包括表达风格和表达学习功能"
[translations.sections.relationship]
name = "关系"
description = "麦麦与用户的关系设置,包括取名功能等"
[translations.sections.chat]
name = "聊天模式"
description = "麦麦的聊天模式和行为设置,包括普通模式、专注模式和自动模式"
[translations.sections.message_receive]
name = "消息接收"
description = "消息过滤和接收设置,可以根据规则过滤特定消息"
[translations.sections.normal_chat]
name = "普通聊天配置"
description = "普通聊天模式下的行为设置,包括回复概率、上下文长度、表情包使用等"
[translations.sections.focus_chat]
name = "专注聊天配置"
description = "专注聊天模式下的行为设置,包括思考间隔、上下文大小等"
[translations.sections.focus_chat_processor]
name = "专注聊天处理器"
description = "专注聊天模式下的处理器设置,包括自我识别、工具使用、工作记忆等功能"
[translations.sections.emoji]
name = "表情包"
description = "表情包相关的设置,包括最大注册数量、替换策略、检查间隔等"
[translations.sections.memory]
name = "记忆"
description = "麦麦的记忆系统设置,包括记忆构建、遗忘、整合等参数"
[translations.sections.mood]
name = "情绪"
description = "麦麦的情绪系统设置,仅在普通聊天模式下有效"
[translations.sections.keyword_reaction]
name = "关键词反应"
description = "针对特定关键词作出反应的设置,仅在普通聊天模式下有效"
[translations.sections.chinese_typo]
name = "错别字生成器"
description = "中文错别字生成器的设置,可以控制错别字生成的概率"
[translations.sections.response_splitter]
name = "回复分割器"
description = "回复分割器的设置,用于控制回复的长度和句子数量"
[translations.sections.model]
name = "模型"
description = "各种AI模型的设置包括组件模型、普通聊天模型、专注聊天模型等"
[translations.sections.maim_message]
name = "消息服务"
description = "消息服务的设置,包括认证令牌、服务器配置等"
[translations.sections.telemetry]
name = "遥测"
description = "统计信息发送设置,用于统计全球麦麦的数量"
[translations.sections.experimental]
name = "实验功能"
description = "实验性功能的设置,包括调试显示、好友聊天等功能"
[translations.items.version]
name = "版本号"
description = "麦麦的版本号,格式:主版本号.次版本号.修订号。主版本号用于不兼容的API修改次版本号用于向下兼容的功能性新增修订号用于向下兼容的问题修正"
[translations.items.qq_account]
name = "QQ账号"
description = "麦麦的QQ账号"
[translations.items.nickname]
name = "昵称"
description = "麦麦的昵称"
[translations.items.alias_names]
name = "别名"
description = "麦麦的其他称呼"
[translations.items.personality_core]
name = "核心性格"
description = "麦麦的核心性格描述建议50字以内"
[translations.items.personality_sides]
name = "性格细节"
description = "麦麦性格的细节描述条数任意不能为0"
[translations.items.identity_detail]
name = "身份细节"
description = "麦麦的身份特征描述可以描述外貌、性别、身高、职业、属性等条数任意不能为0"
[translations.items.expression_style]
name = "表达风格"
description = "麦麦说话的表达风格,表达习惯"
[translations.items.enable_expression_learning]
name = "启用表达学习"
description = "是否启用表达学习功能,麦麦会学习人类说话风格"
[translations.items.learning_interval]
name = "学习间隔"
description = "表达学习的间隔时间(秒)"
[translations.items.give_name]
name = "取名功能"
description = "麦麦是否给其他人取名,关闭后无法使用禁言功能"
[translations.items.chat_mode]
name = "聊天模式"
description = "麦麦的聊天模式normal普通模式token消耗较低、focus专注模式token消耗较高、auto自动模式根据消息内容自动切换"
[translations.items.auto_focus_threshold]
name = "自动专注阈值"
description = "自动切换到专注聊天的阈值,越低越容易进入专注聊天"
[translations.items.exit_focus_threshold]
name = "退出专注阈值"
description = "自动退出专注聊天的阈值,越低越容易退出专注聊天"
[translations.items.ban_words]
name = "禁用词"
description = "需要过滤的词语列表"
[translations.items.ban_msgs_regex]
name = "禁用消息正则"
description = "需要过滤的消息正则表达式,匹配到的消息将被过滤"
[translations.items.normal_chat_first_probability]
name = "首要模型概率"
description = "麦麦回答时选择首要模型的概率与之相对的次要模型的概率为1 - normal_chat_first_probability"
[translations.items.max_context_size]
name = "最大上下文长度"
description = "聊天上下文的最大长度"
[translations.items.emoji_chance]
name = "表情包概率"
description = "麦麦一般回复时使用表情包的概率设置为1让麦麦自己决定发不发"
[translations.items.thinking_timeout]
name = "思考超时"
description = "麦麦最长思考时间超过这个时间的思考会放弃往往是api反应太慢"
[translations.items.willing_mode]
name = "回复意愿模式"
description = "回复意愿的计算模式经典模式classical、mxp模式mxp、自定义模式custom"
[translations.items.talk_frequency]
name = "回复频率"
description = "麦麦回复频率一般为1默认频率下30分钟麦麦回复30条约数"
[translations.items.response_willing_amplifier]
name = "回复意愿放大系数"
description = "麦麦回复意愿放大系数一般为1"
[translations.items.response_interested_rate_amplifier]
name = "兴趣度放大系数"
description = "麦麦回复兴趣度放大系数,听到记忆里的内容时放大系数"
[translations.items.emoji_response_penalty]
name = "表情包回复惩罚"
description = "表情包回复惩罚系数设为0为不回复单个表情包减少单独回复表情包的概率"
[translations.items.mentioned_bot_inevitable_reply]
name = "提及必回"
description = "被提及时是否必然回复"
[translations.items.at_bot_inevitable_reply]
name = "@必回"
description = "被@时是否必然回复"
[translations.items.down_frequency_rate]
name = "降低频率系数"
description = "降低回复频率的群组回复意愿降低系数(除法)"
[translations.items.talk_frequency_down_groups]
name = "降低频率群组"
description = "需要降低回复频率的群组列表"
[translations.items.think_interval]
name = "思考间隔"
description = "思考的时间间隔(秒),可以有效减少消耗"
[translations.items.observation_context_size]
name = "观察上下文大小"
description = "观察到的最长上下文大小建议15太短太长都会导致脑袋尖尖"
[translations.items.compressed_length]
name = "压缩长度"
description = "不能大于observation_context_size心流上下文压缩的最短压缩长度超过心流观察到的上下文长度会压缩最短压缩长度为5"
[translations.items.compress_length_limit]
name = "压缩限制"
description = "最多压缩份数,超过该数值的压缩上下文会被删除"
[translations.items.self_identify_processor]
name = "自我识别处理器"
description = "是否启用自我识别处理器"
[translations.items.tool_use_processor]
name = "工具使用处理器"
description = "是否启用工具使用处理器"
[translations.items.working_memory_processor]
name = "工作记忆处理器"
description = "是否启用工作记忆处理器,不稳定,消耗量大"
[translations.items.max_reg_num]
name = "最大注册数"
description = "表情包最大注册数量"
[translations.items.do_replace]
name = "启用替换"
description = "开启则在达到最大数量时删除(替换)表情包,关闭则达到最大数量时不会继续收集表情包"
[translations.items.check_interval]
name = "检查间隔"
description = "检查表情包(注册,破损,删除)的时间间隔(分钟)"
[translations.items.save_pic]
name = "保存图片"
description = "是否保存表情包图片"
[translations.items.cache_emoji]
name = "缓存表情包"
description = "是否缓存表情包"
[translations.items.steal_emoji]
name = "偷取表情包"
description = "是否偷取表情包,让麦麦可以发送她保存的这些表情包"
[translations.items.content_filtration]
name = "内容过滤"
description = "是否启用表情包过滤,只有符合该要求的表情包才会被保存"
[translations.items.filtration_prompt]
name = "过滤要求"
description = "表情包过滤要求,只有符合该要求的表情包才会被保存"
[translations.items.memory_build_interval]
name = "记忆构建间隔"
description = "记忆构建间隔(秒),间隔越低,麦麦学习越多,但是冗余信息也会增多"
[translations.items.memory_build_distribution]
name = "记忆构建分布"
description = "记忆构建分布参数分布1均值标准差权重分布2均值标准差权重"
[translations.items.memory_build_sample_num]
name = "采样数量"
description = "采样数量,数值越高记忆采样次数越多"
[translations.items.memory_build_sample_length]
name = "采样长度"
description = "采样长度,数值越高一段记忆内容越丰富"
[translations.items.memory_compress_rate]
name = "记忆压缩率"
description = "记忆压缩率,控制记忆精简程度,建议保持默认,调高可以获得更多信息,但是冗余信息也会增多"
[translations.items.forget_memory_interval]
name = "记忆遗忘间隔"
description = "记忆遗忘间隔(秒),间隔越低,麦麦遗忘越频繁,记忆更精简,但更难学习"
[translations.items.memory_forget_time]
name = "遗忘时间"
description = "多长时间后的记忆会被遗忘(小时)"
[translations.items.memory_forget_percentage]
name = "遗忘比例"
description = "记忆遗忘比例,控制记忆遗忘程度,越大遗忘越多,建议保持默认"
[translations.items.consolidate_memory_interval]
name = "记忆整合间隔"
description = "记忆整合间隔(秒),间隔越低,麦麦整合越频繁,记忆更精简"
[translations.items.consolidation_similarity_threshold]
name = "整合相似度阈值"
description = "相似度阈值"
[translations.items.consolidation_check_percentage]
name = "整合检查比例"
description = "检查节点比例"
[translations.items.memory_ban_words]
name = "记忆禁用词"
description = "不希望记忆的词,已经记忆的不会受到影响"
[translations.items.mood_update_interval]
name = "情绪更新间隔"
description = "情绪更新间隔(秒),仅在普通聊天模式下有效"
[translations.items.mood_decay_rate]
name = "情绪衰减率"
description = "情绪衰减率"
[translations.items.mood_intensity_factor]
name = "情绪强度因子"
description = "情绪强度因子"
[translations.items.enable]
name = "启用关键词反应"
description = "关键词反应功能的总开关,仅在普通聊天模式下有效"
[translations.items.chinese_typo_enable]
name = "启用错别字"
description = "是否启用中文错别字生成器"
[translations.items.error_rate]
name = "错误率"
description = "单字替换概率"
[translations.items.min_freq]
name = "最小字频"
description = "最小字频阈值"
[translations.items.tone_error_rate]
name = "声调错误率"
description = "声调错误概率"
[translations.items.word_replace_rate]
name = "整词替换率"
description = "整词替换概率"
[translations.items.splitter_enable]
name = "启用分割器"
description = "是否启用回复分割器"
[translations.items.max_length]
name = "最大长度"
description = "回复允许的最大长度"
[translations.items.max_sentence_num]
name = "最大句子数"
description = "回复允许的最大句子数"
[translations.items.enable_kaomoji_protection]
name = "启用颜文字保护"
description = "是否启用颜文字保护"
[translations.items.model_max_output_length]
name = "最大输出长度"
description = "模型单次返回的最大token数"
[translations.items.auth_token]
name = "认证令牌"
description = "用于API验证的令牌列表为空则不启用验证"
[translations.items.use_custom]
name = "使用自定义"
description = "是否启用自定义的maim_message服务器注意这需要设置新的端口不能与.env重复"
[translations.items.host]
name = "主机地址"
description = "服务器主机地址"
[translations.items.port]
name = "端口"
description = "服务器端口"
[translations.items.mode]
name = "模式"
description = "连接模式ws或tcp"
[translations.items.use_wss]
name = "使用WSS"
description = "是否使用WSS安全连接只支持ws模式"
[translations.items.cert_file]
name = "证书文件"
description = "SSL证书文件路径仅在use_wss=true时有效"
[translations.items.key_file]
name = "密钥文件"
description = "SSL密钥文件路径仅在use_wss=true时有效"
[translations.items.telemetry_enable]
name = "启用遥测"
description = "是否发送统计信息,主要是看全球有多少只麦麦"
[translations.items.debug_show_chat_mode]
name = "显示聊天模式"
description = "是否在回复后显示当前聊天模式"
[translations.items.enable_friend_chat]
name = "启用好友聊天"
description = "是否启用好友聊天功能"
[translations.items.pfc_chatting]
name = "PFC聊天"
description = "暂时无效"
[translations.items."response_splitter.enable"]
name = "启用分割器"
description = "是否启用回复分割器"
[translations.items."chinese_typo.enable"]
name = "启用错别字"
description = "是否启用中文错别字生成器"
[translations.items."keyword_reaction.enable"]
name = "启用关键词反应"
description = "关键词反应功能的总开关,仅在普通聊天模式下有效"