# 角色功能如何使用 ## 什么是角色 角色系统是 CapsWriter-Offline 的 LLM (大语言模型) 后处理功能,可以调用 LLM 的 API 对识别结果进行润色,或当作语音助手进行对话。 你可以定义多个「角色」,每个角色有自己的提示词、模型、输出方式。语音识别完成后,通过**前缀匹配**触发对应角色进行处理。 角色有两种输出方式: - 打字输出,可用作润色 - Toast 弹窗输出,可用作语音助手 比如你用鼠标选中一段文字,然后说: ``` 翻译这段文字 ``` 客户端检测到"翻译"前缀,自动调用对应的 LLM 角色,复制所选文字,调用 LLM API,返回的结果会以 Toast 弹窗显示。 使用角色前,需要编辑角色文件,配置 LLM API,可以用在线服务如 DeepSeek,也可以用本地模型如 LM Studio 或 Ollama。 --- ## 一、角色文件在哪 角色文件存放在项目根目录的 [`LLM/](../LLM/) 文件夹中,每个 `.py` 文件定义**一个角色**。系统启动时会自动加载该目录下所有角色文件,修改后**自动热重载**(3 秒防抖)。 ### 内置角色 | 文件名 | 触发前缀 | 输出模式 | 用途 | |--------|---------|---------|------| | [`default.py](../LLM/default.py) | (默认) | typing | 默认角色,用于润色,已经关闭 | | [`翻译.py](../LLM/翻译.py) | 翻译 | toast | 翻译选中文字 | | [`小助理.py](../LLM/小助理.py) | 小助理 | toast | 问答助手 | --- ## 二、角色文件格式 角色文件是普通的 Python 文件,通过定义顶层变量来配置角色。以下是一个完整示例: ```python # ===== 基本信息 ===== name = '翻译 | translate' # 角色名称,| 分隔多个触发前缀 match = True # 是否启用前缀匹配 process = True # 匹配到后是否处理 # ===== API 配置 ===== provider = 'lmstudio' # API 提供商:'lmstudio', 'ollama', 'openai', 'deepseek', 'moonshot', 'zhipu', 'claude', 'gemini' api_url = '' # 留空则自动使用 provider 对应的默认值 api_key = '' # API Key model = 'local-model' # 模型名称 # ===== 上下文管理 ===== max_context_length = 4096 # 最大上下文长度(token) # ===== 功能开关 ===== enable_hotwords = True # 是否将热词列表放入上下文 enable_history = True # 是否保留对话历史 enable_read_selection = True # 是否读取选中文字(模拟 Ctrl+C) selection_max_length = 1024 # 选中文字最大长度 # ===== 输出配置 ===== output_mode = 'toast' # 'typing' 直接打字 | 'toast' 弹窗 # ===== Toast 外观(仅 toast 模式) ===== toast_font_size = 23 toast_font_color = 'white' toast_bg_color = '#075077' toast_duration = 3000 # 显示时长(毫秒) # ===== 生成参数 ===== temperature = 0.7 top_p = 0.9 max_tokens = 4096 # ===== 提示词定制 ===== prompt_prefix_hotwords = '热词列表:' prompt_prefix_selection = '选中文字:' prompt_prefix_input = '用户输入:' # ===== System Prompt(核心!) ===== system_prompt = ''' 你是一个翻译助手。将用户输入的内容翻译成中文。 如果输入是中文,就翻译成英文。 只输出翻译结果,不要解释。 ''' ``` --- ## 三、核心字段说明 ### name - 触发前缀,语音识别结果以此开头时触发该角色 - 支持 `|` 分隔多个别名,如 `'翻译 | translate'` - 留空表示默认角色 ### process - `True`:走 LLM 处理 - `False`:不使用 LLM,直接输出原始文本(如默认角色) ### output_mode - `'typing'`:模拟键盘逐字打字输出,用于润色 - `'toast'`:在 Toast 浮动窗口中显示(支持 Markdown 渲染),适合翻译、问答等 ### provider 支持的服务商: | provider | 说明 | 默认 API 地址 | |----------|------|-------------| | `ollama` | 本地 Ollama | `http://localhost:11434/v1` | | `lmstudio` | 本地 LM Studio | `http://localhost:1234/v1` | | `openai` | OpenAI | `https://api.openai.com/v1` | | `deepseek` | DeepSeek | `https://api.deepseek.com` | | `moonshot` | 月之暗面 | `https://api.moonshot.cn/v1` | | `zhipu` | 智谱 AI | `https://open.bigmodel.cn/api/paas/v4` | --- ## 四、如何创建新角色 1. 在 `LLM/` 目录下新建一个 `.py` 文件,文件名建议用中文(如 `代码助手.py`) 2. 按照上面的格式定义变量 3. 保存文件,**自动加载**,无需重启 或者直接从已有角色文件复制一份新的,然后修改即可。 其实无需使用多个角色,作者个人只有两个角色: - 小助理,是用的本地 LM Studio 加载的 Gemma4-E4B 模型,翻译、问答都能做 - 大助理,是用的 DeepSeek 的 API --- ## 五、触发机制详述 检测流程: ``` 语音识别结果 → 角色检测器 ↓ 遍历所有角色 ↓ 检查 text 是否以 role.names 之一开头 ├─ 匹配成功 → 去掉前缀和分隔符 → 交给该角色处理 └─ 全部不匹配 → 检查 default.process ├─ True → 交给默认角色处理 └─ False → 不调用 LLM,直接输出 ``` **分隔符清除**:匹配到前缀后,自动去掉紧跟的 `:、,。,. ` 等字符。 --- ## 六、输出模式说明 ### Typing 模式(`'typing'`) - 边生成边模拟键盘打字 - 如果 `config_client.py` 中 `paste = True`,则先完整生成再通过剪贴板粘贴 - 按 `Esc` 可中断输出(由 `llm_stop_key` 配置) ### Toast 模式(`'toast'`) - 在屏幕上的浮动窗口中显示 - **支持 Markdown 渲染**(标题、代码块、列表等) - 可自定义字体、颜色、背景、显示时长 - 鼠标可左键拖拽,右键复制内容,鼠标离开 3 秒后自动关闭 - 键盘 ESC 可手动关闭 --- ## 七、上下文构成 当角色启用相关功能时,LLM 接收到的消息结构如下: ``` System: (角色的 system_prompt) (对话历史,多轮问答记录) 热词列表:[Claude, CapsWriter, ...] ← enable_hotwords 选中文字:被选中的文本内容 ← enable_read_selection 用户输入:用户本次语音输入的内容 ← prompt_prefix_input ``` --- ## 八、配置项 在 [`config_client.py](../config_client.py) 中: ```python paste = False # 是否用粘贴代替打字输出 restore_clip = True # 粘贴后是否恢复剪贴板 paste_apps = ['WeXin.exe', 'Telegram.exe'] # 强制使用粘贴的应用 llm_enabled = True # LLM 总开关 llm_stop_key = 'esc' # 中断输出的快捷键 ``` --- ## 九、实用技巧 ### 1. 开启润色 如果你希望所有语音都经过 LLM 润色,将 `default.py` 中的 `process = False` 改为 `process = True`。 其实,Qwen3-ASR 已经非常强大,加上热词功能,已经完全不需要 LLM 润色功能。毕竟 LLM 处理会增加延迟,降低体验。 在作者的 RTX5050 独显笔记本上,Qwen3-ASR 的短音频延迟最短只有 110ms,体感上是瞬出,识别率又非常好。如果开启润色,每次输出都加上 0.3s 的延迟,体感上就会慢一拍。 只不过 Typeless 有润色,LLM 又这么火,总会有朋友想试试。作者自己试用了 Typeless,表示延迟太大,体验不合格。 ### 2. 多别名触发 ```python name = '翻译 | translate' ``` ### 3. 角色特定热词 如果某个角色 `enable_hotwords = True`,客户端会将 RAG 检索到的潜在热词列表放入 LLM 上下文,帮助 LLM 理解专业术语。 ### 4. 结合选中文字 对于翻译、改写等场景,设置 `enable_read_selection = True`,先选中文字再语音说出指令,LLM 可以同时拿到选中内容和语音输入。 --- ## 十、常见问题 **Q: 修改角色文件后需要重启吗?** 不需要。系统会自动检测 `LLM/` 目录变化,3 秒内自动重载。 **Q: 为什么说了前缀但没有触发角色?** 检查以下几点: - `config_client.py` 中 `llm_enabled = True` - 角色文件中 `process = True` 且 `match = True` - 前缀是否完全匹配(区分中英文) - 查看日志 `logs/client_latest.log` 中的角色检测信息 **Q: 如何暂时禁用一个角色?** 将角色文件中的 `process = False` 或将 `match = False`,保存后自动生效。 **Q: 对话历史会一直累积吗?** 不会。当历史消息的估算 token 总数超过 `max_context_length` 的 80% 时,会自动从最旧的消息开始丢弃。