fix:新增表达方式选择处理器
This commit is contained in:
@@ -1,773 +0,0 @@
|
|||||||
# MaiBot 动作激活系统使用指南
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
MaiBot 的动作激活系统采用**双激活类型架构**,为Focus模式和Normal模式分别提供最优的激活策略。
|
|
||||||
|
|
||||||
**系统已集成四大核心特性:**
|
|
||||||
- 🎯 **双激活类型**:Focus模式智能化,Normal模式高性能
|
|
||||||
- 🚀 **并行判定**:多个LLM判定任务并行执行
|
|
||||||
- 💾 **智能缓存**:相同上下文的判定结果缓存复用
|
|
||||||
- ⚡ **并行动作**:支持与回复同时执行的动作
|
|
||||||
|
|
||||||
## 双激活类型系统 🆕
|
|
||||||
|
|
||||||
### 系统设计理念
|
|
||||||
|
|
||||||
**Focus模式**:智能优先
|
|
||||||
- 支持复杂的LLM判定
|
|
||||||
- 提供精确的上下文理解
|
|
||||||
- 适合需要深度分析的场景
|
|
||||||
|
|
||||||
**Normal模式**:性能优先
|
|
||||||
- 使用快速的关键词匹配
|
|
||||||
- 采用简单的随机触发
|
|
||||||
- 确保快速响应用户
|
|
||||||
|
|
||||||
### 核心属性配置
|
|
||||||
|
|
||||||
```python
|
|
||||||
from src.chat.focus_chat.planners.actions.base_action import BaseAction, register_action, ActionActivationType
|
|
||||||
from src.chat.chat_mode import ChatMode
|
|
||||||
|
|
||||||
@register_action
|
|
||||||
class MyAction(BaseAction):
|
|
||||||
action_name = "my_action"
|
|
||||||
action_description = "我的动作描述"
|
|
||||||
|
|
||||||
# 双激活类型配置
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE # Focus模式使用智能判定
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD # Normal模式使用关键词
|
|
||||||
activation_keywords = ["关键词1", "关键词2", "keyword"]
|
|
||||||
keyword_case_sensitive = False
|
|
||||||
|
|
||||||
# 模式启用控制
|
|
||||||
mode_enable = ChatMode.ALL # 支持的聊天模式
|
|
||||||
|
|
||||||
# 并行执行控制
|
|
||||||
parallel_action = False # 是否与回复并行执行
|
|
||||||
|
|
||||||
# 插件系统控制
|
|
||||||
enable_plugin = True # 是否启用此插件
|
|
||||||
```
|
|
||||||
|
|
||||||
## 激活类型详解
|
|
||||||
|
|
||||||
### 1. ALWAYS - 总是激活
|
|
||||||
**用途**:基础必需动作,始终可用
|
|
||||||
```python
|
|
||||||
focus_activation_type = ActionActivationType.ALWAYS
|
|
||||||
normal_activation_type = ActionActivationType.ALWAYS
|
|
||||||
```
|
|
||||||
**示例**:`reply_action`, `no_reply_action`
|
|
||||||
|
|
||||||
### 2. RANDOM - 随机激活
|
|
||||||
**用途**:增加不可预测性和趣味性
|
|
||||||
```python
|
|
||||||
focus_activation_type = ActionActivationType.RANDOM
|
|
||||||
normal_activation_type = ActionActivationType.RANDOM
|
|
||||||
random_activation_probability = 0.2 # 20%概率激活
|
|
||||||
```
|
|
||||||
**示例**:`vtb_action` (表情动作)
|
|
||||||
|
|
||||||
### 3. LLM_JUDGE - LLM智能判定
|
|
||||||
**用途**:需要上下文理解的复杂判定
|
|
||||||
```python
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
# 注意:Normal模式使用LLM_JUDGE会产生性能警告
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD # 推荐在Normal模式使用KEYWORD
|
|
||||||
```
|
|
||||||
**优化特性**:
|
|
||||||
- ⚡ **直接判定**:直接进行LLM判定,减少复杂度
|
|
||||||
- 🚀 **并行执行**:多个LLM判定同时进行
|
|
||||||
- 💾 **结果缓存**:相同上下文复用结果(30秒有效期)
|
|
||||||
|
|
||||||
### 4. KEYWORD - 关键词触发
|
|
||||||
**用途**:精确命令式触发
|
|
||||||
```python
|
|
||||||
focus_activation_type = ActionActivationType.KEYWORD
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["画", "画图", "生成图片", "draw"]
|
|
||||||
keyword_case_sensitive = False # 不区分大小写
|
|
||||||
```
|
|
||||||
**示例**:`pic_action`, `mute_action`
|
|
||||||
|
|
||||||
## 模式启用控制 (ChatMode)
|
|
||||||
|
|
||||||
### 模式类型
|
|
||||||
```python
|
|
||||||
from src.chat.chat_mode import ChatMode
|
|
||||||
|
|
||||||
# 在所有模式下启用
|
|
||||||
mode_enable = ChatMode.ALL # 默认值
|
|
||||||
|
|
||||||
# 仅在Focus模式启用
|
|
||||||
mode_enable = ChatMode.FOCUS
|
|
||||||
|
|
||||||
# 仅在Normal模式启用
|
|
||||||
mode_enable = ChatMode.NORMAL
|
|
||||||
```
|
|
||||||
|
|
||||||
### 使用场景建议
|
|
||||||
- **ChatMode.ALL**: 通用功能(如回复、图片生成)
|
|
||||||
- **ChatMode.FOCUS**: 需要深度理解的智能功能
|
|
||||||
- **ChatMode.NORMAL**: 快速响应的基础功能
|
|
||||||
|
|
||||||
## 并行动作系统 🆕
|
|
||||||
|
|
||||||
### 概念说明
|
|
||||||
```python
|
|
||||||
# 并行动作:与回复生成同时执行
|
|
||||||
parallel_action = True # 不会阻止回复,提升用户体验
|
|
||||||
|
|
||||||
# 串行动作:替代回复生成(传统行为)
|
|
||||||
parallel_action = False # 默认值,动作执行时不生成回复
|
|
||||||
```
|
|
||||||
|
|
||||||
### 适用场景
|
|
||||||
**并行动作 (parallel_action = True)**:
|
|
||||||
- 情感表达(表情、动作)
|
|
||||||
- 状态变更(禁言、设置)
|
|
||||||
- 辅助功能(TTS播报)
|
|
||||||
|
|
||||||
**串行动作 (parallel_action = False)**:
|
|
||||||
- 内容生成(图片、文档)
|
|
||||||
- 搜索查询
|
|
||||||
- 需要完整注意力的操作
|
|
||||||
|
|
||||||
### 实际案例
|
|
||||||
```python
|
|
||||||
@register_action
|
|
||||||
class MuteAction(PluginAction):
|
|
||||||
action_name = "mute_action"
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["禁言", "mute", "ban", "silence"]
|
|
||||||
parallel_action = True # 禁言的同时还可以回复确认信息
|
|
||||||
|
|
||||||
@register_action
|
|
||||||
class PicAction(PluginAction):
|
|
||||||
action_name = "pic_action"
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["画", "绘制", "生成图片", "画图", "draw", "paint"]
|
|
||||||
parallel_action = False # 专注于图片生成,不同时回复
|
|
||||||
```
|
|
||||||
|
|
||||||
## 推荐配置模式
|
|
||||||
|
|
||||||
### 模式1:智能自适应(推荐)
|
|
||||||
```python
|
|
||||||
# Focus模式智能判定,Normal模式快速触发
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["相关", "关键词", "英文keyword"]
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = False # 根据具体需求调整
|
|
||||||
```
|
|
||||||
|
|
||||||
### 模式2:统一关键词
|
|
||||||
```python
|
|
||||||
# 两个模式都使用关键词,确保行为一致
|
|
||||||
focus_activation_type = ActionActivationType.KEYWORD
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["画", "图片", "生成"]
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = False
|
|
||||||
```
|
|
||||||
|
|
||||||
### 模式3:Focus专享功能
|
|
||||||
```python
|
|
||||||
# 仅在Focus模式启用的高级功能
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.ALWAYS # 不会生效
|
|
||||||
mode_enable = ChatMode.FOCUS
|
|
||||||
parallel_action = False
|
|
||||||
```
|
|
||||||
|
|
||||||
### 模式4:随机娱乐功能
|
|
||||||
```python
|
|
||||||
# 增加趣味性的随机功能
|
|
||||||
focus_activation_type = ActionActivationType.RANDOM
|
|
||||||
normal_activation_type = ActionActivationType.RANDOM
|
|
||||||
random_activation_probability = 0.08 # 8%概率
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = True # 通常与回复并行
|
|
||||||
```
|
|
||||||
|
|
||||||
## 性能优化详解
|
|
||||||
|
|
||||||
### 并行判定机制
|
|
||||||
```python
|
|
||||||
# 自动将多个LLM判定任务并行执行
|
|
||||||
async def _process_llm_judge_actions_parallel(self, llm_judge_actions, ...):
|
|
||||||
tasks = [self._llm_judge_action(name, info, ...) for name, info in llm_judge_actions.items()]
|
|
||||||
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
||||||
```
|
|
||||||
|
|
||||||
**优势**:
|
|
||||||
- 多个LLM判定同时进行,显著减少总耗时
|
|
||||||
- 异常处理确保单个失败不影响整体
|
|
||||||
- 自动负载均衡
|
|
||||||
|
|
||||||
### 智能缓存系统
|
|
||||||
```python
|
|
||||||
# 基于上下文哈希的缓存机制
|
|
||||||
cache_key = f"{action_name}_{context_hash}"
|
|
||||||
if cache_key in self._llm_judge_cache:
|
|
||||||
return cached_result # 直接返回缓存结果
|
|
||||||
```
|
|
||||||
|
|
||||||
**特性**:
|
|
||||||
- 30秒缓存有效期
|
|
||||||
- MD5哈希确保上下文一致性
|
|
||||||
- 自动清理过期缓存
|
|
||||||
- 命中率优化:相同聊天上下文的重复判定
|
|
||||||
|
|
||||||
### 分层判定架构
|
|
||||||
|
|
||||||
#### 第一层:智能动态过滤
|
|
||||||
```python
|
|
||||||
def _pre_filter_llm_actions(self, llm_judge_actions, observed_messages_str, ...):
|
|
||||||
# 动态收集所有KEYWORD类型actions的关键词
|
|
||||||
all_keyword_actions = self.action_manager.get_registered_actions()
|
|
||||||
collected_keywords = {}
|
|
||||||
|
|
||||||
for action_name, action_info in all_keyword_actions.items():
|
|
||||||
if action_info.get("activation_type") == "KEYWORD":
|
|
||||||
keywords = action_info.get("activation_keywords", [])
|
|
||||||
if keywords:
|
|
||||||
collected_keywords[action_name] = [kw.lower() for kw in keywords]
|
|
||||||
|
|
||||||
# 基于实际配置进行智能过滤
|
|
||||||
for action_name, action_info in llm_judge_actions.items():
|
|
||||||
# 策略1: 避免与KEYWORD类型重复
|
|
||||||
# 策略2: 基于action描述进行语义相关性检查
|
|
||||||
# 策略3: 保留核心actions
|
|
||||||
```
|
|
||||||
|
|
||||||
**智能过滤策略**:
|
|
||||||
- **动态关键词收集**:从各个action的实际配置中收集关键词,无硬编码
|
|
||||||
- **重复避免机制**:如果存在对应的KEYWORD触发action,优先使用KEYWORD
|
|
||||||
- **语义相关性检查**:基于action描述和消息内容进行智能匹配
|
|
||||||
- **长度与复杂度匹配**:短消息自动排除复杂operations
|
|
||||||
- **核心action保护**:确保reply/no_reply等基础action始终可用
|
|
||||||
|
|
||||||
#### 第二层:LLM精确判定
|
|
||||||
通过第一层过滤后的动作才进入LLM判定,大幅减少:
|
|
||||||
- LLM调用次数
|
|
||||||
- 总处理时间
|
|
||||||
- API成本
|
|
||||||
|
|
||||||
## HFC流程级并行化优化 🆕
|
|
||||||
|
|
||||||
### 三阶段并行架构
|
|
||||||
|
|
||||||
除了动作激活系统内部的优化,整个HFC(HeartFocus Chat)流程也实现了并行化:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 在 heartFC_chat.py 中的优化
|
|
||||||
if global_config.focus_chat.parallel_processing:
|
|
||||||
# 并行执行调整动作、回忆和处理器阶段
|
|
||||||
with Timer("并行调整动作、回忆和处理", cycle_timers):
|
|
||||||
async def modify_actions_task():
|
|
||||||
await self.action_modifier.modify_actions(observations=self.observations)
|
|
||||||
await self.action_observation.observe()
|
|
||||||
self.observations.append(self.action_observation)
|
|
||||||
return True
|
|
||||||
|
|
||||||
# 创建三个并行任务
|
|
||||||
action_modify_task = asyncio.create_task(modify_actions_task())
|
|
||||||
memory_task = asyncio.create_task(self.memory_activator.activate_memory(self.observations))
|
|
||||||
processor_task = asyncio.create_task(self._process_processors(self.observations, []))
|
|
||||||
|
|
||||||
# 等待三个任务完成
|
|
||||||
_, running_memorys, (all_plan_info, processor_time_costs) = await asyncio.gather(
|
|
||||||
action_modify_task, memory_task, processor_task
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 并行化阶段说明
|
|
||||||
|
|
||||||
**1. 调整动作阶段(Action Modifier)**
|
|
||||||
- 执行动作激活系统的智能判定
|
|
||||||
- 包含并行LLM判定和缓存
|
|
||||||
- 更新可用动作列表
|
|
||||||
|
|
||||||
**2. 回忆激活阶段(Memory Activator)**
|
|
||||||
- 根据当前观察激活相关记忆
|
|
||||||
- 检索历史对话和上下文信息
|
|
||||||
- 为规划器提供背景知识
|
|
||||||
|
|
||||||
**3. 信息处理器阶段(Processors)**
|
|
||||||
- 处理观察信息,提取关键特征
|
|
||||||
- 生成结构化的计划信息
|
|
||||||
- 为规划器提供决策依据
|
|
||||||
|
|
||||||
### 性能提升效果
|
|
||||||
|
|
||||||
**理论提升**:
|
|
||||||
- 原串行执行:500ms + 800ms + 1000ms = 2300ms
|
|
||||||
- 现并行执行:max(500ms, 800ms, 1000ms) = 1000ms
|
|
||||||
- **性能提升:2.3x**
|
|
||||||
|
|
||||||
**实际效果**:
|
|
||||||
- 显著减少每个HFC循环的总耗时
|
|
||||||
- 提高机器人响应速度
|
|
||||||
- 优化用户体验
|
|
||||||
|
|
||||||
### 配置控制
|
|
||||||
|
|
||||||
通过配置文件控制是否启用并行处理:
|
|
||||||
```yaml
|
|
||||||
focus_chat:
|
|
||||||
parallel_processing: true # 启用并行处理
|
|
||||||
```
|
|
||||||
|
|
||||||
**建议设置**:
|
|
||||||
- **生产环境**:启用(`true`)- 获得最佳性能
|
|
||||||
- **调试环境**:可选择禁用(`false`)- 便于问题定位
|
|
||||||
|
|
||||||
## 使用示例
|
|
||||||
|
|
||||||
### 定义新的动作类
|
|
||||||
|
|
||||||
```python
|
|
||||||
from src.chat.focus_chat.planners.actions.plugin_action import PluginAction, register_action, ActionActivationType
|
|
||||||
from src.chat.chat_mode import ChatMode
|
|
||||||
|
|
||||||
@register_action
|
|
||||||
class MyAction(PluginAction):
|
|
||||||
action_name = "my_action"
|
|
||||||
action_description = "我的自定义动作"
|
|
||||||
|
|
||||||
# 双激活类型配置
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["自定义", "触发", "custom"]
|
|
||||||
|
|
||||||
# 模式和并行控制
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = False
|
|
||||||
enable_plugin = True
|
|
||||||
|
|
||||||
async def process(self):
|
|
||||||
# 动作执行逻辑
|
|
||||||
pass
|
|
||||||
```
|
|
||||||
|
|
||||||
### 关键词触发动作
|
|
||||||
```python
|
|
||||||
@register_action
|
|
||||||
class SearchAction(PluginAction):
|
|
||||||
action_name = "search_action"
|
|
||||||
focus_activation_type = ActionActivationType.KEYWORD
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["搜索", "查找", "什么是", "search", "find"]
|
|
||||||
keyword_case_sensitive = False
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = False
|
|
||||||
```
|
|
||||||
|
|
||||||
### 随机触发动作
|
|
||||||
```python
|
|
||||||
@register_action
|
|
||||||
class SurpriseAction(PluginAction):
|
|
||||||
action_name = "surprise_action"
|
|
||||||
focus_activation_type = ActionActivationType.RANDOM
|
|
||||||
normal_activation_type = ActionActivationType.RANDOM
|
|
||||||
random_activation_probability = 0.1 # 10%概率
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = True # 惊喜动作与回复并行
|
|
||||||
```
|
|
||||||
|
|
||||||
### Focus专享智能动作
|
|
||||||
```python
|
|
||||||
@register_action
|
|
||||||
class AdvancedAnalysisAction(PluginAction):
|
|
||||||
action_name = "advanced_analysis"
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.ALWAYS # 不会生效
|
|
||||||
mode_enable = ChatMode.FOCUS # 仅Focus模式
|
|
||||||
parallel_action = False
|
|
||||||
```
|
|
||||||
|
|
||||||
## 现有插件的配置示例
|
|
||||||
|
|
||||||
### MuteAction (禁言动作)
|
|
||||||
```python
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["禁言", "mute", "ban", "silence"]
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = True # 可以与回复同时进行
|
|
||||||
```
|
|
||||||
|
|
||||||
### PicAction (图片生成)
|
|
||||||
```python
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["画", "绘制", "生成图片", "画图", "draw", "paint", "图片生成"]
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = False # 专注生成,不同时回复
|
|
||||||
```
|
|
||||||
|
|
||||||
### VTBAction (虚拟主播表情)
|
|
||||||
```python
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.RANDOM
|
|
||||||
random_activation_probability = 0.08
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = False # 替代文字回复
|
|
||||||
```
|
|
||||||
|
|
||||||
## 性能监控
|
|
||||||
|
|
||||||
### 实时性能指标
|
|
||||||
```python
|
|
||||||
# 自动记录的性能指标
|
|
||||||
logger.debug(f"激活判定:{before_count} -> {after_count} actions")
|
|
||||||
logger.debug(f"并行LLM判定完成,耗时: {duration:.2f}s")
|
|
||||||
logger.debug(f"使用缓存结果 {action_name}: {'激活' if result else '未激活'}")
|
|
||||||
logger.debug(f"清理了 {count} 个过期缓存条目")
|
|
||||||
logger.debug(f"并行调整动作、回忆和处理完成,耗时: {duration:.2f}s")
|
|
||||||
```
|
|
||||||
|
|
||||||
### 性能优化建议
|
|
||||||
1. **合理配置缓存时间**:根据聊天活跃度调整 `_cache_expiry_time`
|
|
||||||
2. **优化过滤规则**:根据实际使用情况调整 `_quick_filter_keywords`
|
|
||||||
3. **监控并行效果**:关注 `asyncio.gather` 的执行时间
|
|
||||||
4. **缓存命中率**:监控缓存使用情况,优化策略
|
|
||||||
5. **启用流程并行化**:确保 `parallel_processing` 配置为 `true`
|
|
||||||
6. **激活类型选择**:Normal模式优先使用KEYWORD,避免LLM_JUDGE
|
|
||||||
|
|
||||||
## 迁移指南 ⚠️
|
|
||||||
|
|
||||||
### 重大变更说明
|
|
||||||
**旧的 `action_activation_type` 属性已被移除**,必须更新为新的双激活类型系统。
|
|
||||||
|
|
||||||
### 快速迁移步骤
|
|
||||||
|
|
||||||
#### 第一步:更新基本属性
|
|
||||||
```python
|
|
||||||
# 旧的配置(已废弃)❌
|
|
||||||
class OldAction(BaseAction):
|
|
||||||
action_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
|
|
||||||
# 新的配置(必须使用)✅
|
|
||||||
class NewAction(BaseAction):
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["相关", "关键词"]
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = False
|
|
||||||
enable_plugin = True
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 第二步:根据原类型选择对应策略
|
|
||||||
```python
|
|
||||||
# 原来是 ALWAYS
|
|
||||||
focus_activation_type = ActionActivationType.ALWAYS
|
|
||||||
normal_activation_type = ActionActivationType.ALWAYS
|
|
||||||
|
|
||||||
# 原来是 LLM_JUDGE
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD # 添加关键词
|
|
||||||
activation_keywords = ["需要", "添加", "关键词"]
|
|
||||||
|
|
||||||
# 原来是 KEYWORD
|
|
||||||
focus_activation_type = ActionActivationType.KEYWORD
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
# 保持原有的 activation_keywords
|
|
||||||
|
|
||||||
# 原来是 RANDOM
|
|
||||||
focus_activation_type = ActionActivationType.RANDOM
|
|
||||||
normal_activation_type = ActionActivationType.RANDOM
|
|
||||||
# 保持原有的 random_activation_probability
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 第三步:配置新功能
|
|
||||||
```python
|
|
||||||
# 添加模式控制
|
|
||||||
mode_enable = ChatMode.ALL # 或 ChatMode.FOCUS / ChatMode.NORMAL
|
|
||||||
|
|
||||||
# 添加并行控制
|
|
||||||
parallel_action = False # 根据动作特性选择True/False
|
|
||||||
|
|
||||||
# 添加插件控制
|
|
||||||
enable_plugin = True # 是否启用此插件
|
|
||||||
```
|
|
||||||
|
|
||||||
### 批量迁移脚本
|
|
||||||
可以创建以下脚本来帮助批量迁移:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# migrate_actions.py
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
|
|
||||||
def migrate_action_file(filepath):
|
|
||||||
with open(filepath, 'r', encoding='utf-8') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
# 替换 action_activation_type
|
|
||||||
if 'action_activation_type = ActionActivationType.ALWAYS' in content:
|
|
||||||
content = content.replace(
|
|
||||||
'action_activation_type = ActionActivationType.ALWAYS',
|
|
||||||
'focus_activation_type = ActionActivationType.ALWAYS\n normal_activation_type = ActionActivationType.ALWAYS'
|
|
||||||
)
|
|
||||||
elif 'action_activation_type = ActionActivationType.LLM_JUDGE' in content:
|
|
||||||
content = content.replace(
|
|
||||||
'action_activation_type = ActionActivationType.LLM_JUDGE',
|
|
||||||
'focus_activation_type = ActionActivationType.LLM_JUDGE\n normal_activation_type = ActionActivationType.KEYWORD\n activation_keywords = ["需要", "添加", "关键词"] # TODO: 配置合适的关键词'
|
|
||||||
)
|
|
||||||
# ... 其他替换逻辑
|
|
||||||
|
|
||||||
# 添加新属性
|
|
||||||
if 'mode_enable' not in content:
|
|
||||||
# 在class定义后添加新属性
|
|
||||||
# ...
|
|
||||||
|
|
||||||
with open(filepath, 'w', encoding='utf-8') as f:
|
|
||||||
f.write(content)
|
|
||||||
|
|
||||||
# 使用示例
|
|
||||||
migrate_action_file('src/plugins/your_plugin/actions/your_action.py')
|
|
||||||
```
|
|
||||||
|
|
||||||
## 测试验证
|
|
||||||
|
|
||||||
运行动作激活优化测试:
|
|
||||||
```bash
|
|
||||||
python test_action_activation_optimized.py
|
|
||||||
```
|
|
||||||
|
|
||||||
运行HFC并行化测试:
|
|
||||||
```bash
|
|
||||||
python test_parallel_optimization.py
|
|
||||||
```
|
|
||||||
|
|
||||||
测试内容包括:
|
|
||||||
- ✅ 双激活类型功能验证
|
|
||||||
- ✅ 并行处理功能验证
|
|
||||||
- ✅ 缓存机制效果测试
|
|
||||||
- ✅ 分层判定规则验证
|
|
||||||
- ✅ 性能对比分析
|
|
||||||
- ✅ HFC流程并行化效果
|
|
||||||
- ✅ 多循环平均性能测试
|
|
||||||
- ✅ 并行动作系统验证
|
|
||||||
- ✅ 迁移兼容性测试
|
|
||||||
|
|
||||||
## 最佳实践
|
|
||||||
|
|
||||||
### 1. 激活类型选择
|
|
||||||
- **ALWAYS**:reply, no_reply 等基础动作
|
|
||||||
- **LLM_JUDGE**:需要智能判断的复杂动作(建议仅用于Focus模式)
|
|
||||||
- **KEYWORD**:明确的命令式动作(推荐在Normal模式使用)
|
|
||||||
- **RANDOM**:增趣动作,低概率触发
|
|
||||||
|
|
||||||
### 2. 双模式配置策略
|
|
||||||
- **智能自适应**:Focus用LLM_JUDGE,Normal用KEYWORD
|
|
||||||
- **性能优先**:两个模式都用KEYWORD或RANDOM
|
|
||||||
- **功能分离**:某些功能仅在特定模式启用
|
|
||||||
|
|
||||||
### 3. 并行动作使用建议
|
|
||||||
- **parallel_action = True**:辅助性、非内容生成类动作
|
|
||||||
- **parallel_action = False**:主要内容生成、需要完整注意力的动作
|
|
||||||
|
|
||||||
### 4. LLM判定提示词编写
|
|
||||||
- 明确描述激活条件和排除条件
|
|
||||||
- 避免模糊的描述
|
|
||||||
- 考虑边界情况
|
|
||||||
- 保持简洁明了
|
|
||||||
|
|
||||||
### 5. 关键词设置
|
|
||||||
- 包含同义词和英文对应词
|
|
||||||
- 考虑用户的不同表达习惯
|
|
||||||
- 避免过于宽泛的关键词
|
|
||||||
- 根据实际使用调整
|
|
||||||
|
|
||||||
### 6. 性能优化
|
|
||||||
- 定期监控处理时间
|
|
||||||
- 根据使用模式调整缓存策略
|
|
||||||
- 优化激活判定逻辑
|
|
||||||
- 平衡准确性和性能
|
|
||||||
- **启用并行处理配置**
|
|
||||||
- **Normal模式避免使用LLM_JUDGE**
|
|
||||||
|
|
||||||
### 7. 并行化最佳实践
|
|
||||||
- 在生产环境启用 `parallel_processing`
|
|
||||||
- 监控并行阶段的执行时间
|
|
||||||
- 确保各阶段的独立性
|
|
||||||
- 避免共享状态导致的竞争条件
|
|
||||||
|
|
||||||
## 总结
|
|
||||||
|
|
||||||
优化后的动作激活系统通过**五层优化策略**,实现了全方位的性能提升:
|
|
||||||
|
|
||||||
### 第一层:双激活类型系统
|
|
||||||
- **Focus模式**:智能化优先,支持复杂LLM判定
|
|
||||||
- **Normal模式**:性能优先,使用快速关键词匹配
|
|
||||||
- **模式自适应**:根据聊天模式选择最优策略
|
|
||||||
|
|
||||||
### 第二层:动作激活内部优化
|
|
||||||
- **并行判定**:多个LLM判定任务并行执行
|
|
||||||
- **智能缓存**:相同上下文的判定结果缓存复用
|
|
||||||
- **分层判定**:快速过滤 + 精确判定的两层架构
|
|
||||||
|
|
||||||
### 第三层:并行动作系统
|
|
||||||
- **并行执行**:支持动作与回复同时进行
|
|
||||||
- **用户体验**:减少等待时间,提升交互流畅性
|
|
||||||
- **灵活控制**:每个动作可独立配置并行行为
|
|
||||||
|
|
||||||
### 第四层:HFC流程级并行化
|
|
||||||
- **三阶段并行**:调整动作、回忆、处理器同时执行
|
|
||||||
- **性能提升**:2.3x 理论加速比
|
|
||||||
- **配置控制**:可根据环境灵活开启/关闭
|
|
||||||
|
|
||||||
### 第五层:插件系统增强
|
|
||||||
- **enable_plugin**:精确控制插件启用状态
|
|
||||||
- **mode_enable**:支持模式级别的功能控制
|
|
||||||
- **向后兼容**:平滑迁移旧系统配置
|
|
||||||
|
|
||||||
### 综合效果
|
|
||||||
- **响应速度**:显著提升机器人反应速度
|
|
||||||
- **成本优化**:减少不必要的LLM调用
|
|
||||||
- **智能决策**:双激活类型覆盖所有场景
|
|
||||||
- **用户体验**:更快速、更智能的交互
|
|
||||||
- **灵活配置**:精细化的功能控制
|
|
||||||
|
|
||||||
**总性能提升预估:4-6x**
|
|
||||||
- 双激活类型系统:1.5x (Normal模式优化)
|
|
||||||
- 动作激活内部优化:1.5-2x
|
|
||||||
- HFC流程并行化:2.3x
|
|
||||||
- 并行动作系统:额外30-50%提升
|
|
||||||
- 缓存和过滤优化:额外20-30%提升
|
|
||||||
|
|
||||||
这使得MaiBot能够更快速、更智能地响应用户需求,同时提供灵活的配置选项以适应不同的使用场景,实现了卓越的交互体验。
|
|
||||||
|
|
||||||
## 如何为Action添加激活类型
|
|
||||||
|
|
||||||
### 对于普通Action
|
|
||||||
|
|
||||||
```python
|
|
||||||
from src.chat.focus_chat.planners.actions.base_action import BaseAction, register_action, ActionActivationType
|
|
||||||
from src.chat.chat_mode import ChatMode
|
|
||||||
|
|
||||||
@register_action
|
|
||||||
class YourAction(BaseAction):
|
|
||||||
action_name = "your_action"
|
|
||||||
action_description = "你的动作描述"
|
|
||||||
|
|
||||||
# 双激活类型配置
|
|
||||||
focus_activation_type = ActionActivationType.LLM_JUDGE
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["关键词1", "关键词2", "keyword"]
|
|
||||||
keyword_case_sensitive = False
|
|
||||||
|
|
||||||
# 新增属性
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = False
|
|
||||||
enable_plugin = True
|
|
||||||
|
|
||||||
# ... 其他代码
|
|
||||||
```
|
|
||||||
|
|
||||||
### 对于插件Action
|
|
||||||
|
|
||||||
```python
|
|
||||||
from src.chat.focus_chat.planners.actions.plugin_action import PluginAction, register_action, ActionActivationType
|
|
||||||
from src.chat.chat_mode import ChatMode
|
|
||||||
|
|
||||||
@register_action
|
|
||||||
class YourPluginAction(PluginAction):
|
|
||||||
action_name = "your_plugin_action"
|
|
||||||
action_description = "你的插件动作描述"
|
|
||||||
|
|
||||||
# 双激活类型配置
|
|
||||||
focus_activation_type = ActionActivationType.KEYWORD
|
|
||||||
normal_activation_type = ActionActivationType.KEYWORD
|
|
||||||
activation_keywords = ["触发词1", "trigger", "启动"]
|
|
||||||
keyword_case_sensitive = False
|
|
||||||
|
|
||||||
# 新增属性
|
|
||||||
mode_enable = ChatMode.ALL
|
|
||||||
parallel_action = True # 与回复并行执行
|
|
||||||
enable_plugin = True
|
|
||||||
|
|
||||||
# ... 其他代码
|
|
||||||
```
|
|
||||||
|
|
||||||
## 工作流程
|
|
||||||
|
|
||||||
1. **ActionModifier处理**: 在planner运行前,ActionModifier会遍历所有注册的动作
|
|
||||||
2. **模式检查**: 根据当前聊天模式(Focus/Normal)和action的mode_enable进行过滤
|
|
||||||
3. **激活类型判断**: 根据当前模式选择对应的激活类型(focus_activation_type或normal_activation_type)
|
|
||||||
4. **激活决策**:
|
|
||||||
- ALWAYS: 直接激活
|
|
||||||
- RANDOM: 根据概率随机决定
|
|
||||||
- LLM_JUDGE: 调用小模型判定(Normal模式会警告)
|
|
||||||
- KEYWORD: 检测关键词匹配
|
|
||||||
5. **并行性检查**: 根据parallel_action决定是否与回复并行
|
|
||||||
6. **结果收集**: 收集所有激活的动作供planner使用
|
|
||||||
|
|
||||||
## 配置建议
|
|
||||||
|
|
||||||
### 双激活类型策略选择
|
|
||||||
- **智能自适应(推荐)**: Focus用LLM_JUDGE,Normal用KEYWORD
|
|
||||||
- **性能优先**: 两个模式都用KEYWORD或RANDOM
|
|
||||||
- **功能专享**: 某些高级功能仅在Focus模式启用
|
|
||||||
|
|
||||||
### LLM判定提示词编写
|
|
||||||
- 明确指出激活条件和不激活条件
|
|
||||||
- 使用简单清晰的语言
|
|
||||||
- 避免过于复杂的逻辑判断
|
|
||||||
|
|
||||||
### 随机概率设置
|
|
||||||
- 核心功能: 不建议使用随机
|
|
||||||
- 娱乐功能: 0.1-0.3 (10%-30%)
|
|
||||||
- 辅助功能: 0.05-0.2 (5%-20%)
|
|
||||||
|
|
||||||
### 关键词设计
|
|
||||||
- 包含常用的同义词和变体
|
|
||||||
- 考虑中英文兼容
|
|
||||||
- 避免过于宽泛的词汇
|
|
||||||
- 测试关键词的覆盖率
|
|
||||||
|
|
||||||
### 性能考虑
|
|
||||||
- LLM判定会增加响应时间,适度使用
|
|
||||||
- 关键词检测性能最好,推荐优先使用
|
|
||||||
- Normal模式避免使用LLM_JUDGE
|
|
||||||
- 建议优先级:KEYWORD > ALWAYS > RANDOM > LLM_JUDGE
|
|
||||||
|
|
||||||
## 调试和测试
|
|
||||||
|
|
||||||
使用提供的测试脚本验证激活类型系统:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python test_action_activation.py
|
|
||||||
```
|
|
||||||
|
|
||||||
该脚本会显示:
|
|
||||||
- 所有注册动作的双激活类型配置
|
|
||||||
- 模拟不同模式下的激活结果
|
|
||||||
- 并行动作系统的工作状态
|
|
||||||
- 帮助验证配置是否正确
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. **重大变更**: `action_activation_type` 已被移除,必须使用双激活类型
|
|
||||||
2. **向后兼容**: 系统不再兼容旧的单一激活类型配置
|
|
||||||
3. **错误处理**: LLM判定失败时默认不激活该动作
|
|
||||||
4. **性能警告**: Normal模式使用LLM_JUDGE会产生警告
|
|
||||||
5. **日志记录**: 系统会记录激活决策过程,便于调试
|
|
||||||
6. **性能影响**: LLM判定会略微增加响应时间
|
|
||||||
|
|
||||||
## 未来扩展
|
|
||||||
|
|
||||||
系统设计支持未来添加更多激活类型和功能,如:
|
|
||||||
- 基于时间的激活
|
|
||||||
- 基于用户权限的激活
|
|
||||||
- 基于群组设置的激活
|
|
||||||
- 基于对话历史的激活
|
|
||||||
- 基于情感状态的激活
|
|
||||||
@@ -8,12 +8,12 @@ description = "展示新插件系统完整功能的示例插件"
|
|||||||
|
|
||||||
# 组件启用控制
|
# 组件启用控制
|
||||||
[components]
|
[components]
|
||||||
enable_greeting = true
|
enable_greeting = false
|
||||||
enable_helpful = true
|
enable_helpful = true
|
||||||
enable_help = true
|
enable_help = false
|
||||||
enable_send = true
|
enable_send = false
|
||||||
enable_echo = true
|
enable_echo = false
|
||||||
enable_info = true
|
enable_info = false
|
||||||
enable_dice = true
|
enable_dice = true
|
||||||
|
|
||||||
# 智能问候配置
|
# 智能问候配置
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ from src.chat.focus_chat.replyer.default_replyer import DefaultReplyer
|
|||||||
from src.chat.focus_chat.memory_activator import MemoryActivator
|
from src.chat.focus_chat.memory_activator import MemoryActivator
|
||||||
from src.chat.focus_chat.info_processors.base_processor import BaseProcessor
|
from src.chat.focus_chat.info_processors.base_processor import BaseProcessor
|
||||||
from src.chat.focus_chat.info_processors.self_processor import SelfProcessor
|
from src.chat.focus_chat.info_processors.self_processor import SelfProcessor
|
||||||
|
from src.chat.focus_chat.info_processors.expression_selector_processor import ExpressionSelectorProcessor
|
||||||
from src.chat.focus_chat.planners.planner_factory import PlannerFactory
|
from src.chat.focus_chat.planners.planner_factory import PlannerFactory
|
||||||
from src.chat.focus_chat.planners.modify_actions import ActionModifier
|
from src.chat.focus_chat.planners.modify_actions import ActionModifier
|
||||||
from src.chat.focus_chat.planners.action_manager import ActionManager
|
from src.chat.focus_chat.planners.action_manager import ActionManager
|
||||||
@@ -48,6 +49,7 @@ PROCESSOR_CLASSES = {
|
|||||||
"WorkingMemoryProcessor": (WorkingMemoryProcessor, "working_memory_processor"),
|
"WorkingMemoryProcessor": (WorkingMemoryProcessor, "working_memory_processor"),
|
||||||
"SelfProcessor": (SelfProcessor, "self_identify_processor"),
|
"SelfProcessor": (SelfProcessor, "self_identify_processor"),
|
||||||
"RelationshipProcessor": (RelationshipProcessor, "relation_processor"),
|
"RelationshipProcessor": (RelationshipProcessor, "relation_processor"),
|
||||||
|
"ExpressionSelectorProcessor": (ExpressionSelectorProcessor, "expression_selector_processor"),
|
||||||
}
|
}
|
||||||
|
|
||||||
logger = get_logger("hfc") # Logger Name Changed
|
logger = get_logger("hfc") # Logger Name Changed
|
||||||
@@ -189,6 +191,7 @@ class HeartFChatting:
|
|||||||
"WorkingMemoryProcessor",
|
"WorkingMemoryProcessor",
|
||||||
"SelfProcessor",
|
"SelfProcessor",
|
||||||
"RelationshipProcessor",
|
"RelationshipProcessor",
|
||||||
|
"ExpressionSelectorProcessor",
|
||||||
]:
|
]:
|
||||||
self.processors.append(processor_actual_class(subheartflow_id=self.stream_id))
|
self.processors.append(processor_actual_class(subheartflow_id=self.stream_id))
|
||||||
elif name == "ChattingInfoProcessor":
|
elif name == "ChattingInfoProcessor":
|
||||||
|
|||||||
71
src/chat/focus_chat/info/expression_selection_info.py
Normal file
71
src/chat/focus_chat/info/expression_selection_info.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import List, Dict, Any
|
||||||
|
from .info_base import InfoBase
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ExpressionSelectionInfo(InfoBase):
|
||||||
|
"""表达选择信息类
|
||||||
|
|
||||||
|
用于存储和管理选中的表达方式信息。
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
type (str): 信息类型标识符,默认为 "expression_selection"
|
||||||
|
data (Dict[str, Any]): 包含选中表达方式的数据字典
|
||||||
|
"""
|
||||||
|
|
||||||
|
type: str = "expression_selection"
|
||||||
|
|
||||||
|
def get_selected_expressions(self) -> List[Dict[str, str]]:
|
||||||
|
"""获取选中的表达方式列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[Dict[str, str]]: 选中的表达方式列表
|
||||||
|
"""
|
||||||
|
return self.get_info("selected_expressions") or []
|
||||||
|
|
||||||
|
def set_selected_expressions(self, expressions: List[Dict[str, str]]) -> None:
|
||||||
|
"""设置选中的表达方式列表
|
||||||
|
|
||||||
|
Args:
|
||||||
|
expressions: 选中的表达方式列表
|
||||||
|
"""
|
||||||
|
self.data["selected_expressions"] = expressions
|
||||||
|
|
||||||
|
def get_expressions_count(self) -> int:
|
||||||
|
"""获取选中表达方式的数量
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: 表达方式数量
|
||||||
|
"""
|
||||||
|
return len(self.get_selected_expressions())
|
||||||
|
|
||||||
|
def get_processed_info(self) -> str:
|
||||||
|
"""获取处理后的信息
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 处理后的信息字符串
|
||||||
|
"""
|
||||||
|
expressions = self.get_selected_expressions()
|
||||||
|
if not expressions:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# 格式化表达方式为可读文本
|
||||||
|
formatted_expressions = []
|
||||||
|
for expr in expressions:
|
||||||
|
situation = expr.get("situation", "")
|
||||||
|
style = expr.get("style", "")
|
||||||
|
expr_type = expr.get("type", "")
|
||||||
|
|
||||||
|
if situation and style:
|
||||||
|
formatted_expressions.append(f"当{situation}时,使用 {style}")
|
||||||
|
|
||||||
|
return "\n".join(formatted_expressions)
|
||||||
|
|
||||||
|
def get_expressions_for_action_data(self) -> List[Dict[str, str]]:
|
||||||
|
"""获取用于action_data的表达方式数据
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[Dict[str, str]]: 格式化后的表达方式数据
|
||||||
|
"""
|
||||||
|
return self.get_selected_expressions()
|
||||||
@@ -0,0 +1,365 @@
|
|||||||
|
import time
|
||||||
|
import random
|
||||||
|
from typing import List, Dict
|
||||||
|
from src.chat.heart_flow.observation.chatting_observation import ChattingObservation
|
||||||
|
from src.chat.heart_flow.observation.observation import Observation
|
||||||
|
from src.llm_models.utils_model import LLMRequest
|
||||||
|
from src.config.config import global_config
|
||||||
|
from src.common.logger import get_logger
|
||||||
|
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
|
||||||
|
from src.chat.message_receive.chat_stream import get_chat_manager
|
||||||
|
from .base_processor import BaseProcessor
|
||||||
|
from src.chat.focus_chat.info.info_base import InfoBase
|
||||||
|
from src.chat.focus_chat.info.expression_selection_info import ExpressionSelectionInfo
|
||||||
|
from src.chat.focus_chat.expressors.exprssion_learner import get_expression_learner
|
||||||
|
from json_repair import repair_json
|
||||||
|
import json
|
||||||
|
|
||||||
|
logger = get_logger("processor")
|
||||||
|
|
||||||
|
|
||||||
|
def weighted_sample_no_replacement(items, weights, k) -> list:
|
||||||
|
"""
|
||||||
|
加权随机抽样,不允许重复
|
||||||
|
|
||||||
|
Args:
|
||||||
|
items: 待抽样的项目列表
|
||||||
|
weights: 对应项目的权重列表
|
||||||
|
k: 抽样数量
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
抽样结果列表
|
||||||
|
"""
|
||||||
|
if not items or k <= 0:
|
||||||
|
return []
|
||||||
|
|
||||||
|
k = min(k, len(items))
|
||||||
|
selected = []
|
||||||
|
remaining_items = list(items)
|
||||||
|
remaining_weights = list(weights)
|
||||||
|
|
||||||
|
for _ in range(k):
|
||||||
|
if not remaining_items:
|
||||||
|
break
|
||||||
|
|
||||||
|
# 计算累积权重
|
||||||
|
total_weight = sum(remaining_weights)
|
||||||
|
if total_weight <= 0:
|
||||||
|
# 如果权重都为0或负数,则随机选择
|
||||||
|
selected_index = random.randint(0, len(remaining_items) - 1)
|
||||||
|
else:
|
||||||
|
# 加权随机选择
|
||||||
|
rand_val = random.uniform(0, total_weight)
|
||||||
|
cumulative_weight = 0
|
||||||
|
selected_index = 0
|
||||||
|
for i, weight in enumerate(remaining_weights):
|
||||||
|
cumulative_weight += weight
|
||||||
|
if rand_val <= cumulative_weight:
|
||||||
|
selected_index = i
|
||||||
|
break
|
||||||
|
|
||||||
|
# 添加选中的项目
|
||||||
|
selected.append(remaining_items[selected_index])
|
||||||
|
# 移除已选中的项目
|
||||||
|
remaining_items.pop(selected_index)
|
||||||
|
remaining_weights.pop(selected_index)
|
||||||
|
|
||||||
|
return selected
|
||||||
|
|
||||||
|
|
||||||
|
def init_prompt():
|
||||||
|
expression_evaluation_prompt = """
|
||||||
|
你的名字是{bot_name}
|
||||||
|
|
||||||
|
以下是正在进行的聊天内容:
|
||||||
|
{chat_observe_info}
|
||||||
|
|
||||||
|
以下是可选的表达情境:
|
||||||
|
{all_situations}
|
||||||
|
|
||||||
|
请你分析聊天内容的语境、情绪、话题类型,从上述情境中选择最适合当前聊天情境的10个情境。
|
||||||
|
考虑因素包括:
|
||||||
|
1. 聊天的情绪氛围(轻松、严肃、幽默等)
|
||||||
|
2. 话题类型(日常、技术、游戏、情感等)
|
||||||
|
3. 情境与当前语境的匹配度
|
||||||
|
|
||||||
|
请以JSON格式输出,只需要输出选中的情境编号:
|
||||||
|
{{
|
||||||
|
"selected_situations": [1, 3, 5, 7, 9, 12, 15, 18, 21, 25]
|
||||||
|
}}
|
||||||
|
|
||||||
|
请严格按照JSON格式输出,不要包含其他内容:
|
||||||
|
"""
|
||||||
|
Prompt(expression_evaluation_prompt, "expression_evaluation_prompt")
|
||||||
|
|
||||||
|
|
||||||
|
class ExpressionSelectorProcessor(BaseProcessor):
|
||||||
|
log_prefix = "表达选择器"
|
||||||
|
|
||||||
|
def __init__(self, subheartflow_id: str):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.subheartflow_id = subheartflow_id
|
||||||
|
self.last_selection_time = 0
|
||||||
|
self.selection_interval = 60 # 1分钟间隔
|
||||||
|
self.cached_expressions = [] # 缓存上一次选择的表达方式
|
||||||
|
|
||||||
|
# 表达方式选择模式
|
||||||
|
self.selection_mode = getattr(global_config.expression, "selection_mode", "llm") # "llm" 或 "random"
|
||||||
|
|
||||||
|
self.llm_model = LLMRequest(
|
||||||
|
model=global_config.model.utils_small,
|
||||||
|
request_type="focus.processor.expression_selector",
|
||||||
|
)
|
||||||
|
|
||||||
|
name = get_chat_manager().get_stream_name(self.subheartflow_id)
|
||||||
|
self.log_prefix = f"[{name}] 表达选择器"
|
||||||
|
|
||||||
|
async def process_info(self, observations: List[Observation] = None, *infos) -> List[InfoBase]:
|
||||||
|
"""处理信息对象
|
||||||
|
|
||||||
|
Args:
|
||||||
|
observations: 观察对象列表
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List[InfoBase]: 处理后的表达选择信息列表
|
||||||
|
"""
|
||||||
|
current_time = time.time()
|
||||||
|
|
||||||
|
# 检查频率限制
|
||||||
|
if current_time - self.last_selection_time < self.selection_interval:
|
||||||
|
logger.debug(f"{self.log_prefix} 距离上次选择不足{self.selection_interval}秒,使用缓存的表达方式")
|
||||||
|
# 使用缓存的表达方式
|
||||||
|
if self.cached_expressions:
|
||||||
|
# 从缓存的15个中随机选5个
|
||||||
|
final_expressions = random.sample(self.cached_expressions, min(5, len(self.cached_expressions)))
|
||||||
|
|
||||||
|
# 创建表达选择信息
|
||||||
|
expression_info = ExpressionSelectionInfo()
|
||||||
|
expression_info.set_selected_expressions(final_expressions)
|
||||||
|
|
||||||
|
logger.info(f"{self.log_prefix} 使用缓存选择了{len(final_expressions)}个表达方式")
|
||||||
|
return [expression_info]
|
||||||
|
else:
|
||||||
|
logger.debug(f"{self.log_prefix} 没有缓存的表达方式,跳过选择")
|
||||||
|
return []
|
||||||
|
|
||||||
|
# 获取聊天内容
|
||||||
|
chat_info = ""
|
||||||
|
if observations:
|
||||||
|
for observation in observations:
|
||||||
|
if isinstance(observation, ChattingObservation):
|
||||||
|
chat_info = observation.get_observe_info()
|
||||||
|
break
|
||||||
|
|
||||||
|
if not chat_info:
|
||||||
|
logger.debug(f"{self.log_prefix} 没有聊天内容,跳过表达方式选择")
|
||||||
|
return []
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 根据模式选择表达方式
|
||||||
|
if self.selection_mode == "llm":
|
||||||
|
# LLM模式:调用LLM选择15个,然后随机选5个
|
||||||
|
selected_expressions = await self._select_suitable_expressions_llm(chat_info)
|
||||||
|
cache_size = len(selected_expressions) if selected_expressions else 0
|
||||||
|
mode_desc = f"LLM模式(已缓存{cache_size}个)"
|
||||||
|
else:
|
||||||
|
# 随机模式:直接随机选择5个
|
||||||
|
selected_expressions = await self._select_suitable_expressions_random(chat_info)
|
||||||
|
cache_size = len(selected_expressions) if selected_expressions else 0
|
||||||
|
mode_desc = f"随机模式(已缓存{cache_size}个)"
|
||||||
|
|
||||||
|
if selected_expressions:
|
||||||
|
# 缓存选择的表达方式
|
||||||
|
self.cached_expressions = selected_expressions
|
||||||
|
# 更新最后选择时间
|
||||||
|
self.last_selection_time = current_time
|
||||||
|
|
||||||
|
# 从选择的表达方式中随机选5个
|
||||||
|
final_expressions = random.sample(selected_expressions, min(4, len(selected_expressions)))
|
||||||
|
|
||||||
|
# 创建表达选择信息
|
||||||
|
expression_info = ExpressionSelectionInfo()
|
||||||
|
expression_info.set_selected_expressions(final_expressions)
|
||||||
|
|
||||||
|
logger.info(f"{self.log_prefix} 为当前聊天选择了{len(final_expressions)}个表达方式({mode_desc})")
|
||||||
|
return [expression_info]
|
||||||
|
else:
|
||||||
|
logger.debug(f"{self.log_prefix} 未选择任何表达方式")
|
||||||
|
return []
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{self.log_prefix} 处理表达方式选择时出错: {e}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
async def _get_random_expressions(self) -> tuple[List[Dict], List[Dict], List[Dict]]:
|
||||||
|
"""随机获取表达方式:20个style,20个grammar,20个personality"""
|
||||||
|
expression_learner = get_expression_learner()
|
||||||
|
|
||||||
|
# 获取所有表达方式
|
||||||
|
(
|
||||||
|
learnt_style_expressions,
|
||||||
|
learnt_grammar_expressions,
|
||||||
|
personality_expressions,
|
||||||
|
) = await expression_learner.get_expression_by_chat_id(self.subheartflow_id)
|
||||||
|
|
||||||
|
# 随机选择
|
||||||
|
selected_style = random.sample(learnt_style_expressions, min(15, len(learnt_style_expressions)))
|
||||||
|
selected_grammar = random.sample(learnt_grammar_expressions, min(15, len(learnt_grammar_expressions)))
|
||||||
|
selected_personality = random.sample(personality_expressions, min(5, len(personality_expressions)))
|
||||||
|
|
||||||
|
return selected_style, selected_grammar, selected_personality
|
||||||
|
|
||||||
|
async def _select_suitable_expressions_llm(self, chat_info: str) -> List[Dict[str, str]]:
|
||||||
|
"""使用LLM选择适合的表达方式"""
|
||||||
|
|
||||||
|
# 1. 获取35个随机表达方式
|
||||||
|
style_exprs, grammar_exprs, personality_exprs = await self._get_random_expressions()
|
||||||
|
|
||||||
|
# 2. 构建所有表达方式的索引和情境列表
|
||||||
|
all_expressions = []
|
||||||
|
all_situations = []
|
||||||
|
|
||||||
|
# 添加style表达方式
|
||||||
|
for expr in style_exprs:
|
||||||
|
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
||||||
|
expr_with_type = expr.copy()
|
||||||
|
expr_with_type["type"] = "style"
|
||||||
|
all_expressions.append(expr_with_type)
|
||||||
|
all_situations.append(f"{len(all_expressions)}. [语言风格] {expr['situation']}")
|
||||||
|
|
||||||
|
# 添加grammar表达方式
|
||||||
|
for expr in grammar_exprs:
|
||||||
|
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
||||||
|
expr_with_type = expr.copy()
|
||||||
|
expr_with_type["type"] = "grammar"
|
||||||
|
all_expressions.append(expr_with_type)
|
||||||
|
all_situations.append(f"{len(all_expressions)}. [句法语法] {expr['situation']}")
|
||||||
|
|
||||||
|
# 添加personality表达方式
|
||||||
|
for expr in personality_exprs:
|
||||||
|
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
||||||
|
expr_with_type = expr.copy()
|
||||||
|
expr_with_type["type"] = "personality"
|
||||||
|
all_expressions.append(expr_with_type)
|
||||||
|
all_situations.append(f"{len(all_expressions)}. [个性表达] {expr['situation']}")
|
||||||
|
|
||||||
|
if not all_expressions:
|
||||||
|
logger.warning(f"{self.log_prefix} 没有找到可用的表达方式")
|
||||||
|
return []
|
||||||
|
|
||||||
|
all_situations_str = "\n".join(all_situations)
|
||||||
|
|
||||||
|
# 3. 构建prompt(只包含情境,不包含完整的表达方式)
|
||||||
|
prompt = (await global_prompt_manager.get_prompt_async("expression_evaluation_prompt")).format(
|
||||||
|
bot_name=global_config.bot.nickname,
|
||||||
|
chat_observe_info=chat_info,
|
||||||
|
all_situations=all_situations_str,
|
||||||
|
)
|
||||||
|
|
||||||
|
# 4. 调用LLM
|
||||||
|
try:
|
||||||
|
content, _ = await self.llm_model.generate_response_async(prompt=prompt)
|
||||||
|
|
||||||
|
logger.info(f"{self.log_prefix} LLM返回结果: {content}")
|
||||||
|
|
||||||
|
if not content:
|
||||||
|
logger.warning(f"{self.log_prefix} LLM返回空结果")
|
||||||
|
return []
|
||||||
|
|
||||||
|
# 5. 解析结果
|
||||||
|
result = repair_json(content)
|
||||||
|
if isinstance(result, str):
|
||||||
|
result = json.loads(result)
|
||||||
|
|
||||||
|
if not isinstance(result, dict) or "selected_situations" not in result:
|
||||||
|
logger.error(f"{self.log_prefix} LLM返回格式错误")
|
||||||
|
return []
|
||||||
|
|
||||||
|
selected_indices = result["selected_situations"]
|
||||||
|
|
||||||
|
# 根据索引获取完整的表达方式
|
||||||
|
valid_expressions = []
|
||||||
|
for idx in selected_indices:
|
||||||
|
if isinstance(idx, int) and 1 <= idx <= len(all_expressions):
|
||||||
|
valid_expressions.append(all_expressions[idx - 1]) # 索引从1开始
|
||||||
|
|
||||||
|
logger.info(f"{self.log_prefix} LLM从{len(all_expressions)}个情境中选择了{len(valid_expressions)}个")
|
||||||
|
return valid_expressions
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{self.log_prefix} LLM处理表达方式选择时出错: {e}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
async def _select_suitable_expressions_random(self, chat_info: str) -> List[Dict[str, str]]:
|
||||||
|
"""随机选择表达方式(原replyer逻辑)"""
|
||||||
|
|
||||||
|
# 获取所有表达方式
|
||||||
|
expression_learner = get_expression_learner()
|
||||||
|
(
|
||||||
|
learnt_style_expressions,
|
||||||
|
learnt_grammar_expressions,
|
||||||
|
personality_expressions,
|
||||||
|
) = await expression_learner.get_expression_by_chat_id(self.subheartflow_id)
|
||||||
|
|
||||||
|
selected_expressions = []
|
||||||
|
|
||||||
|
# 1. learnt_style_expressions相似度匹配选择3条
|
||||||
|
if learnt_style_expressions:
|
||||||
|
similar_exprs = self._find_similar_expressions(chat_info, learnt_style_expressions, 3)
|
||||||
|
for expr in similar_exprs:
|
||||||
|
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
||||||
|
expr_copy = expr.copy()
|
||||||
|
expr_copy["type"] = "style"
|
||||||
|
selected_expressions.append(expr_copy)
|
||||||
|
|
||||||
|
# 2. learnt_grammar_expressions加权随机选2条
|
||||||
|
if learnt_grammar_expressions:
|
||||||
|
weights = [expr.get("count", 1) for expr in learnt_grammar_expressions]
|
||||||
|
selected_learnt = weighted_sample_no_replacement(learnt_grammar_expressions, weights, 2)
|
||||||
|
for expr in selected_learnt:
|
||||||
|
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
||||||
|
expr_copy = expr.copy()
|
||||||
|
expr_copy["type"] = "grammar"
|
||||||
|
selected_expressions.append(expr_copy)
|
||||||
|
|
||||||
|
# 3. personality_expressions随机选1条
|
||||||
|
if personality_expressions:
|
||||||
|
expr = random.choice(personality_expressions)
|
||||||
|
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
||||||
|
expr_copy = expr.copy()
|
||||||
|
expr_copy["type"] = "personality"
|
||||||
|
selected_expressions.append(expr_copy)
|
||||||
|
|
||||||
|
logger.info(f"{self.log_prefix} 随机模式选择了{len(selected_expressions)}个表达方式")
|
||||||
|
return selected_expressions
|
||||||
|
|
||||||
|
def _find_similar_expressions(self, input_text: str, expressions: List[Dict], top_k: int = 3) -> List[Dict]:
|
||||||
|
"""使用简单的文本匹配找出相似的表达方式(简化版,避免依赖sklearn)"""
|
||||||
|
if not expressions or not input_text:
|
||||||
|
return random.sample(expressions, min(top_k, len(expressions))) if expressions else []
|
||||||
|
|
||||||
|
# 简单的关键词匹配
|
||||||
|
scored_expressions = []
|
||||||
|
input_words = set(input_text.lower().split())
|
||||||
|
|
||||||
|
for expr in expressions:
|
||||||
|
situation = expr.get("situation", "").lower()
|
||||||
|
situation_words = set(situation.split())
|
||||||
|
|
||||||
|
# 计算交集大小作为相似度
|
||||||
|
similarity = len(input_words & situation_words)
|
||||||
|
scored_expressions.append((similarity, expr))
|
||||||
|
|
||||||
|
# 按相似度排序
|
||||||
|
scored_expressions.sort(key=lambda x: x[0], reverse=True)
|
||||||
|
|
||||||
|
# 如果没有匹配的,随机选择
|
||||||
|
if all(score == 0 for score, _ in scored_expressions):
|
||||||
|
return random.sample(expressions, min(top_k, len(expressions)))
|
||||||
|
|
||||||
|
# 返回top_k个最相似的
|
||||||
|
return [expr for _, expr in scored_expressions[:top_k]]
|
||||||
|
|
||||||
|
|
||||||
|
init_prompt()
|
||||||
@@ -11,6 +11,7 @@ from src.chat.focus_chat.info.action_info import ActionInfo
|
|||||||
from src.chat.focus_chat.info.structured_info import StructuredInfo
|
from src.chat.focus_chat.info.structured_info import StructuredInfo
|
||||||
from src.chat.focus_chat.info.self_info import SelfInfo
|
from src.chat.focus_chat.info.self_info import SelfInfo
|
||||||
from src.chat.focus_chat.info.relation_info import RelationInfo
|
from src.chat.focus_chat.info.relation_info import RelationInfo
|
||||||
|
from src.chat.focus_chat.info.expression_selection_info import ExpressionSelectionInfo
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
|
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
|
||||||
from src.individuality.individuality import get_individuality
|
from src.individuality.individuality import get_individuality
|
||||||
@@ -122,6 +123,7 @@ class ActionPlanner(BasePlanner):
|
|||||||
chat_type = "group"
|
chat_type = "group"
|
||||||
is_group_chat = True
|
is_group_chat = True
|
||||||
relation_info = ""
|
relation_info = ""
|
||||||
|
selected_expressions = []
|
||||||
for info in all_plan_info:
|
for info in all_plan_info:
|
||||||
if isinstance(info, ObsInfo):
|
if isinstance(info, ObsInfo):
|
||||||
observed_messages = info.get_talking_message()
|
observed_messages = info.get_talking_message()
|
||||||
@@ -136,6 +138,8 @@ class ActionPlanner(BasePlanner):
|
|||||||
relation_info = info.get_processed_info()
|
relation_info = info.get_processed_info()
|
||||||
elif isinstance(info, StructuredInfo):
|
elif isinstance(info, StructuredInfo):
|
||||||
structured_info = info.get_processed_info()
|
structured_info = info.get_processed_info()
|
||||||
|
elif isinstance(info, ExpressionSelectionInfo):
|
||||||
|
selected_expressions = info.get_expressions_for_action_data()
|
||||||
else:
|
else:
|
||||||
extra_info.append(info.get_processed_info())
|
extra_info.append(info.get_processed_info())
|
||||||
# elif not isinstance(info, ActionInfo): # 跳过已处理的ActionInfo
|
# elif not isinstance(info, ActionInfo): # 跳过已处理的ActionInfo
|
||||||
@@ -238,6 +242,11 @@ class ActionPlanner(BasePlanner):
|
|||||||
if relation_info:
|
if relation_info:
|
||||||
action_data["relation_info_block"] = relation_info
|
action_data["relation_info_block"] = relation_info
|
||||||
|
|
||||||
|
# 将选中的表达方式传递给action_data
|
||||||
|
if selected_expressions:
|
||||||
|
action_data["selected_expressions"] = selected_expressions
|
||||||
|
logger.debug(f"{self.log_prefix} 传递{len(selected_expressions)}个选中的表达方式到action_data")
|
||||||
|
|
||||||
# 对于reply动作不需要额外处理,因为相关字段已经在上面的循环中添加到action_data
|
# 对于reply动作不需要额外处理,因为相关字段已经在上面的循环中添加到action_data
|
||||||
|
|
||||||
if extracted_action not in current_available_actions:
|
if extracted_action not in current_available_actions:
|
||||||
|
|||||||
@@ -268,6 +268,7 @@ class DefaultReplyer:
|
|||||||
sender_name=sender, # Pass determined name
|
sender_name=sender, # Pass determined name
|
||||||
target_message=targer,
|
target_message=targer,
|
||||||
config_expression_style=global_config.expression.expression_style,
|
config_expression_style=global_config.expression.expression_style,
|
||||||
|
action_data=action_data, # 传递action_data
|
||||||
)
|
)
|
||||||
|
|
||||||
# 4. 调用 LLM 生成回复
|
# 4. 调用 LLM 生成回复
|
||||||
@@ -324,6 +325,7 @@ class DefaultReplyer:
|
|||||||
identity,
|
identity,
|
||||||
target_message,
|
target_message,
|
||||||
config_expression_style,
|
config_expression_style,
|
||||||
|
action_data=None,
|
||||||
# stuation,
|
# stuation,
|
||||||
) -> str:
|
) -> str:
|
||||||
is_group_chat = bool(chat_stream.group_info)
|
is_group_chat = bool(chat_stream.group_info)
|
||||||
@@ -343,35 +345,24 @@ class DefaultReplyer:
|
|||||||
show_actions=True,
|
show_actions=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
expression_learner = get_expression_learner()
|
|
||||||
(
|
|
||||||
learnt_style_expressions,
|
|
||||||
learnt_grammar_expressions,
|
|
||||||
personality_expressions,
|
|
||||||
) = await expression_learner.get_expression_by_chat_id(chat_stream.stream_id)
|
|
||||||
|
|
||||||
style_habbits = []
|
style_habbits = []
|
||||||
grammar_habbits = []
|
grammar_habbits = []
|
||||||
# 1. learnt_expressions加权随机选3条
|
|
||||||
if learnt_style_expressions:
|
# 使用从处理器传来的选中表达方式
|
||||||
# 使用相似度匹配选择最相似的表达
|
selected_expressions = action_data.get("selected_expressions", []) if action_data else []
|
||||||
similar_exprs = find_similar_expressions(target_message, learnt_style_expressions, 3)
|
|
||||||
for expr in similar_exprs:
|
if selected_expressions:
|
||||||
# print(f"expr: {expr}")
|
logger.info(f"{self.log_prefix} 使用处理器选中的{len(selected_expressions)}个表达方式")
|
||||||
|
for expr in selected_expressions:
|
||||||
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
||||||
style_habbits.append(f"当{expr['situation']}时,使用 {expr['style']}")
|
expr_type = expr.get("type", "style")
|
||||||
# 2. learnt_grammar_expressions加权随机选2条
|
if expr_type == "grammar":
|
||||||
if learnt_grammar_expressions:
|
grammar_habbits.append(f"当{expr['situation']}时,使用 {expr['style']}")
|
||||||
weights = [expr["count"] for expr in learnt_grammar_expressions]
|
else:
|
||||||
selected_learnt = weighted_sample_no_replacement(learnt_grammar_expressions, weights, 2)
|
style_habbits.append(f"当{expr['situation']}时,使用 {expr['style']}")
|
||||||
for expr in selected_learnt:
|
else:
|
||||||
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
logger.debug(f"{self.log_prefix} 没有从处理器获得表达方式,将使用空的表达方式")
|
||||||
grammar_habbits.append(f"当{expr['situation']}时,使用 {expr['style']}")
|
# 不再在replyer中进行随机选择,全部交给处理器处理
|
||||||
# 3. personality_expressions随机选1条
|
|
||||||
if personality_expressions:
|
|
||||||
expr = random.choice(personality_expressions)
|
|
||||||
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
|
||||||
style_habbits.append(f"当{expr['situation']}时,使用 {expr['style']}")
|
|
||||||
|
|
||||||
style_habbits_str = "\n".join(style_habbits)
|
style_habbits_str = "\n".join(style_habbits)
|
||||||
grammar_habbits_str = "\n".join(grammar_habbits)
|
grammar_habbits_str = "\n".join(grammar_habbits)
|
||||||
|
|||||||
@@ -807,7 +807,7 @@ class NormalChat:
|
|||||||
time_elapsed = current_time - stats["first_time"]
|
time_elapsed = current_time - stats["first_time"]
|
||||||
total_messages = self._get_total_messages_in_timerange(stats["first_time"], stats["last_time"])
|
total_messages = self._get_total_messages_in_timerange(stats["first_time"], stats["last_time"])
|
||||||
|
|
||||||
print(f"person_id: {person_id}, total_messages: {total_messages}, time_elapsed: {time_elapsed}")
|
# print(f"person_id: {person_id}, total_messages: {total_messages}, time_elapsed: {time_elapsed}")
|
||||||
|
|
||||||
# 检查是否满足关系构建条件
|
# 检查是否满足关系构建条件
|
||||||
should_build_relation = (
|
should_build_relation = (
|
||||||
|
|||||||
@@ -182,6 +182,9 @@ class FocusChatProcessorConfig(ConfigBase):
|
|||||||
working_memory_processor: bool = True
|
working_memory_processor: bool = True
|
||||||
"""是否启用工作记忆处理器"""
|
"""是否启用工作记忆处理器"""
|
||||||
|
|
||||||
|
expression_selector_processor: bool = True
|
||||||
|
"""是否启用表达方式选择处理器"""
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ExpressionConfig(ConfigBase):
|
class ExpressionConfig(ConfigBase):
|
||||||
@@ -196,6 +199,9 @@ class ExpressionConfig(ConfigBase):
|
|||||||
enable_expression_learning: bool = True
|
enable_expression_learning: bool = True
|
||||||
"""是否启用表达学习"""
|
"""是否启用表达学习"""
|
||||||
|
|
||||||
|
selection_mode: str = "llm"
|
||||||
|
"""表达方式选择模式:'llm' 使用LLM智能选择,'random' 使用传统随机选择"""
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class EmojiConfig(ConfigBase):
|
class EmojiConfig(ConfigBase):
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ class RelationshipManager:
|
|||||||
days_diff = hours_diff / 24 - 7
|
days_diff = hours_diff / 24 - 7
|
||||||
return max(0.1, 0.95 - days_diff * (0.85 / 23))
|
return max(0.1, 0.95 - days_diff * (0.85 / 23))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"计算时间权重失败: {e}")
|
logger.error(f"计算时间权重失败: {e}")
|
||||||
return 0.5 # 发生错误时返回中等权重
|
return 0.5 # 发生错误时返回中等权重
|
||||||
|
|
||||||
def tfidf_similarity(self, s1, s2):
|
def tfidf_similarity(self, s1, s2):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[inner]
|
[inner]
|
||||||
version = "2.22.0"
|
version = "2.23.0"
|
||||||
|
|
||||||
#----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读----
|
#----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读----
|
||||||
#如果你想要修改配置文件,请在修改后将version的值进行变更
|
#如果你想要修改配置文件,请在修改后将version的值进行变更
|
||||||
@@ -43,6 +43,7 @@ identity_detail = [
|
|||||||
expression_style = "描述麦麦说话的表达风格,表达习惯,例如:(回复尽量简短一些。可以参考贴吧,知乎和微博的回复风格,回复不要浮夸,不要用夸张修辞,平淡一些。不要有额外的符号,尽量简单简短)"
|
expression_style = "描述麦麦说话的表达风格,表达习惯,例如:(回复尽量简短一些。可以参考贴吧,知乎和微博的回复风格,回复不要浮夸,不要用夸张修辞,平淡一些。不要有额外的符号,尽量简单简短)"
|
||||||
enable_expression_learning = false # 是否启用表达学习,麦麦会学习不同群里人类说话风格(群之间不互通)
|
enable_expression_learning = false # 是否启用表达学习,麦麦会学习不同群里人类说话风格(群之间不互通)
|
||||||
learning_interval = 600 # 学习间隔 单位秒
|
learning_interval = 600 # 学习间隔 单位秒
|
||||||
|
selection_mode = "llm" # 专注模式下 表达方式选择模式:'llm' 使用LLM智能选择,'random' 使用传统随机选择
|
||||||
|
|
||||||
[relationship]
|
[relationship]
|
||||||
enable_relationship = true # 是否启用关系系统
|
enable_relationship = true # 是否启用关系系统
|
||||||
|
|||||||
Reference in New Issue
Block a user