feat:内置频率调整,减轻Planner负担

pull/1299/head
SengokuCola 2025-10-14 13:17:08 +08:00
parent a97d8b4e3d
commit 36d95848d1
12 changed files with 126 additions and 106 deletions

View File

@ -44,7 +44,7 @@
## 🔥 更新和安装 ## 🔥 更新和安装
**最新版本: v0.10.3** ([更新日志](changelogs/changelog.md)) **最新版本: v0.11.0** ([更新日志](changelogs/changelog.md))
可前往 [Release](https://github.com/MaiM-with-u/MaiBot/releases/) 页面下载最新版本 可前往 [Release](https://github.com/MaiM-with-u/MaiBot/releases/) 页面下载最新版本
可前往 [启动器发布页面](https://github.com/MaiM-with-u/mailauncher/releases/)下载最新启动器 可前往 [启动器发布页面](https://github.com/MaiM-with-u/mailauncher/releases/)下载最新启动器

View File

@ -1,75 +0,0 @@
# BetterFrequency 频率控制插件
这是一个用于控制MaiBot聊天频率的插件支持实时调整talk_frequency参数。
## 功能特性
- 💬 **Talk Frequency控制**: 调整机器人的发言频率
- 📊 **状态显示**: 实时查看当前频率控制状态
- ⚡ **实时生效**: 设置后立即生效,无需重启
- 💾 **不保存消息**: 命令执行反馈不会保存到数据库
- 🚀 **简化命令**: 支持完整命令和简化命令两种形式
## 命令列表
### 1. 设置Talk Frequency
```
/chat talk_frequency <数字> # 完整命令
/chat t <数字> # 简化命令
```
- 功能设置当前聊天的talk_frequency调整值
- 参数支持0到1之间的数值
- 示例:
- `/chat talk_frequency 1.0``/chat t 1.0` - 设置发言频率调整为1.0(最高频率)
- `/chat talk_frequency 0.5``/chat t 0.5` - 设置发言频率调整为0.5
- `/chat talk_frequency 0.0``/chat t 0.0` - 设置发言频率调整为0.0(最低频率)
### 2. 显示当前状态
```
/chat show # 完整命令
/chat s # 简化命令
```
- 功能:显示当前聊天的频率控制状态
- 显示内容:
- 当前talk_frequency值
- 可用命令提示(包含简化命令)
## 配置说明
插件配置文件 `config.toml` 包含以下选项:
```toml
[plugin]
name = "better_frequency_plugin"
version = "1.0.0"
enabled = true
[frequency]
default_talk_adjust = 1.0 # 默认talk_frequency调整值
max_adjust_value = 1.0 # 最大调整值
min_adjust_value = 0.0 # 最小调整值
```
## 使用场景
- **提高机器人活跃度**: 设置较高的talk_frequency值接近1.0
- **降低机器人活跃度**: 设置较低的talk_frequency值接近0.0
- **精细调节**: 使用小数进行微调
- **实时监控**: 通过show命令查看当前状态
- **快速操作**: 使用简化命令提高操作效率
## 注意事项
1. 调整值会立即生效,影响当前聊天的机器人行为
2. 命令执行反馈消息不会保存到数据库
3. 支持0到1之间的数值
4. 每个聊天都有独立的频率控制设置
5. 简化命令和完整命令功能完全相同,可根据个人习惯选择
## 技术实现
- 基于MaiCore插件系统开发
- 使用frequency_api进行频率控制操作
- 使用send_api发送反馈消息
- 支持异步操作和错误处理
- 正则表达式支持多种命令格式

View File

@ -2,7 +2,7 @@
"manifest_version": 1, "manifest_version": 1,
"name": "发言频率控制插件|BetterFrequency Plugin", "name": "发言频率控制插件|BetterFrequency Plugin",
"version": "2.0.0", "version": "2.0.0",
"description": "控制聊天频率支持设置focus_value和talk_frequency调整值提供完整命令和简化命令", "description": "控制聊天频率支持设置focus_value和talk_frequency调整值提供命令",
"author": { "author": {
"name": "SengokuCola", "name": "SengokuCola",
"url": "https://github.com/MaiM-with-u" "url": "https://github.com/MaiM-with-u"
@ -30,12 +30,6 @@
"description": "设置当前聊天的talk_frequency调整值", "description": "设置当前聊天的talk_frequency调整值",
"pattern": "/chat talk_frequency <数字> 或 /chat t <数字>" "pattern": "/chat talk_frequency <数字> 或 /chat t <数字>"
}, },
{
"type": "action",
"name": "frequency_adjust",
"description": "调整当前聊天的发言频率",
"pattern": "/chat frequency_adjust <数字> 或 /chat f <数字>"
},
{ {
"type": "command", "type": "command",
"name": "show_frequency", "name": "show_frequency",

View File

@ -55,7 +55,7 @@ class FrequencyAdjustAction(BaseAction):
return False, error_msg return False, error_msg
# 2. 获取当前频率值 # 2. 获取当前频率值
current_frequency = frequency_api.get_current_talk_frequency(self.chat_id) current_frequency = frequency_api.get_current_talk_value(self.chat_id)
# 3. 计算新的频率值(使用比率而不是绝对值) # 3. 计算新的频率值(使用比率而不是绝对值)
# calculated_frequency = current_frequency * multiply # calculated_frequency = current_frequency * multiply

View File

@ -37,9 +37,13 @@ class SetTalkFrequencyCommand(BaseCommand):
# 设置talk_frequency # 设置talk_frequency
frequency_api.set_talk_frequency_adjust(chat_id, value) frequency_api.set_talk_frequency_adjust(chat_id, value)
final_value = frequency_api.get_current_talk_value(chat_id)
adjust_value = frequency_api.get_talk_frequency_adjust(chat_id)
base_value = final_value / adjust_value
# 发送反馈消息(不保存到数据库) # 发送反馈消息(不保存到数据库)
await send_api.text_to_stream( await send_api.text_to_stream(
f"已设置当前聊天的talk_frequency调整值为: {value}", f"已设置当前聊天的talk_frequency调整值为: {value}\n当前talk_value: {final_value:.2f}\n发言频率调整: {adjust_value:.2f}\n基础值: {base_value:.2f}",
chat_id, chat_id,
storage_message=False storage_message=False
) )
@ -71,12 +75,16 @@ class ShowFrequencyCommand(BaseCommand):
chat_id = self.message.chat_stream.stream_id chat_id = self.message.chat_stream.stream_id
# 获取当前频率控制状态 # 获取当前频率控制状态
current_talk_frequency = frequency_api.get_current_talk_frequency(chat_id) current_talk_frequency = frequency_api.get_current_talk_value(chat_id)
talk_frequency_adjust = frequency_api.get_talk_frequency_adjust(chat_id) talk_frequency_adjust = frequency_api.get_talk_frequency_adjust(chat_id)
base_value = current_talk_frequency / talk_frequency_adjust
# 构建显示消息 # 构建显示消息
status_msg = f"""当前聊天频率控制状态 status_msg = f"""当前聊天频率控制状态
Talk Frequency (发言频率): Talk Value (发言频率):
基础值: {base_value:.2f}
发言频率调整: {talk_frequency_adjust:.2f}
当前值: {current_talk_frequency:.2f} 当前值: {current_talk_frequency:.2f}
使用命令: 使用命令:
@ -120,7 +128,7 @@ class BetterFrequencyPlugin(BasePlugin):
config_schema: dict = { config_schema: dict = {
"plugin": { "plugin": {
"name": ConfigField(type=str, default="better_frequency_plugin", description="插件名称"), "name": ConfigField(type=str, default="better_frequency_plugin", description="插件名称"),
"version": ConfigField(type=str, default="1.0.1", description="插件版本"), "version": ConfigField(type=str, default="1.0.2", description="插件版本"),
"enabled": ConfigField(type=bool, default=True, description="是否启用插件"), "enabled": ConfigField(type=bool, default=True, description="是否启用插件"),
}, },
"frequency": { "frequency": {
@ -128,10 +136,10 @@ class BetterFrequencyPlugin(BasePlugin):
"max_adjust_value": ConfigField(type=float, default=1.0, description="最大调整值"), "max_adjust_value": ConfigField(type=float, default=1.0, description="最大调整值"),
"min_adjust_value": ConfigField(type=float, default=0.0, description="最小调整值"), "min_adjust_value": ConfigField(type=float, default=0.0, description="最小调整值"),
}, },
"features": { # "features": {
"enable_frequency_adjust_action": ConfigField(type=bool, default=False, description="是否启用频率调节动作FrequencyAdjustAction"), # "enable_frequency_adjust_action": ConfigField(type=bool, default=False, description="是否启用频率调节动作FrequencyAdjustAction"),
"enable_commands": ConfigField(type=bool, default=True, description="是否启用命令功能(/chat命令"), # "enable_commands": ConfigField(type=bool, default=True, description="是否启用命令功能(/chat命令"),
} # }
} }
def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]: def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]:
@ -145,7 +153,7 @@ class BetterFrequencyPlugin(BasePlugin):
]) ])
# 根据配置决定是否注册频率调节动作组件 # 根据配置决定是否注册频率调节动作组件
if self.config.get("features", {}).get("enable_frequency_adjust_action", True): # if self.config.get("features", {}).get("enable_frequency_adjust_action", True):
components.append((FrequencyAdjustAction.get_action_info(), FrequencyAdjustAction)) # components.append((FrequencyAdjustAction.get_action_info(), FrequencyAdjustAction))
return components return components

View File

@ -1,5 +1,33 @@
from datetime import datetime
import time
from typing import Dict from typing import Dict
from src.chat.utils.chat_message_builder import (
get_raw_msg_by_timestamp_with_chat,
build_readable_messages,
)
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.config.config import global_config, model_config
from src.llm_models.utils_model import LLMRequest
from src.common.logger import get_logger
from src.plugin_system.apis import frequency_api
def init_prompt():
Prompt(
"""{name_block}
{time_block}
你现在正在聊天请根据下面的聊天记录判断是否有用户觉得你的发言过于频繁或者发言过少
{message_str}
如果用户觉得你的发言过于频繁请输出"过于频繁"否则输出"正常"
如果用户觉得你的发言过少请输出"过少"否则输出"正常"
""",
"frequency_adjust_prompt",
)
logger = get_logger("frequency_control")
class FrequencyControl: class FrequencyControl:
"""简化的频率控制类仅管理不同chat_id的频率值""" """简化的频率控制类仅管理不同chat_id的频率值"""
@ -8,6 +36,11 @@ class FrequencyControl:
self.chat_id = chat_id self.chat_id = chat_id
# 发言频率调整值 # 发言频率调整值
self.talk_frequency_adjust: float = 1.0 self.talk_frequency_adjust: float = 1.0
self.last_frequency_adjust_time: float = 0.0
self.frequency_model = LLMRequest(
model_set=model_config.model_task_config.utils_small, request_type="frequency.adjust"
)
def get_talk_frequency_adjust(self) -> float: def get_talk_frequency_adjust(self) -> float:
"""获取发言频率调整值""" """获取发言频率调整值"""
@ -16,7 +49,67 @@ class FrequencyControl:
def set_talk_frequency_adjust(self, value: float) -> None: def set_talk_frequency_adjust(self, value: float) -> None:
"""设置发言频率调整值""" """设置发言频率调整值"""
self.talk_frequency_adjust = max(0.1, min(5.0, value)) self.talk_frequency_adjust = max(0.1, min(5.0, value))
async def trigger_frequency_adjust(self) -> None:
msg_list = get_raw_msg_by_timestamp_with_chat(
chat_id=self.chat_id,
timestamp_start=self.last_frequency_adjust_time,
timestamp_end=time.time(),
)
if time.time() - self.last_frequency_adjust_time < 120 or len(msg_list) <= 5:
return
else:
new_msg_list = get_raw_msg_by_timestamp_with_chat(
chat_id=self.chat_id,
timestamp_start=self.last_frequency_adjust_time,
timestamp_end=time.time(),
limit=5,
limit_mode="latest",
)
message_str = build_readable_messages(
new_msg_list,
replace_bot_name=True,
timestamp_mode="relative",
read_mark=0.0,
show_actions=False,
)
time_block = f"当前时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
bot_name = global_config.bot.nickname
bot_nickname = (
f",也有人叫你{','.join(global_config.bot.alias_names)}" if global_config.bot.alias_names else ""
)
name_block = f"你的名字是{bot_name}{bot_nickname},请注意哪些是你自己的发言。"
prompt = await global_prompt_manager.format_prompt(
"frequency_adjust_prompt",
name_block=name_block,
time_block=time_block,
message_str=message_str,
)
response, (reasoning_content, _, _) = await self.frequency_model.generate_response_async(
prompt,
)
logger.info(f"频率调整 prompt: {prompt}")
logger.info(f"频率调整 response: {response}")
if global_config.debug.show_prompt:
logger.info(f"频率调整 prompt: {prompt}")
logger.info(f"频率调整 response: {response}")
logger.info(f"频率调整 reasoning_content: {reasoning_content}")
final_value_by_api = frequency_api.get_current_talk_value(self.chat_id)
if "过于频繁" in response:
logger.info(f"频率调整: 过于频繁,调整值到{final_value_by_api}")
self.talk_frequency_adjust = max(0.1, min(3.0, self.talk_frequency_adjust * 0.8))
elif "过少" in response:
logger.info(f"频率调整: 过少,调整值到{final_value_by_api}")
self.talk_frequency_adjust = max(0.1, min(3.0, self.talk_frequency_adjust * 1.2))
self.last_frequency_adjust_time = time.time()
class FrequencyControlManager: class FrequencyControlManager:
"""频率控制管理器,管理多个聊天流的频率控制实例""" """频率控制管理器,管理多个聊天流的频率控制实例"""
@ -41,6 +134,7 @@ class FrequencyControlManager:
"""获取所有有频率控制的聊天ID""" """获取所有有频率控制的聊天ID"""
return list(self.frequency_control_dict.keys()) return list(self.frequency_control_dict.keys())
init_prompt()
# 创建全局实例 # 创建全局实例
frequency_control_manager = FrequencyControlManager() frequency_control_manager = FrequencyControlManager()

View File

@ -330,7 +330,8 @@ class HeartFChatting:
async with global_prompt_manager.async_message_scope(self.chat_stream.context.get_template_name()): async with global_prompt_manager.async_message_scope(self.chat_stream.context.get_template_name()):
asyncio.create_task(self.expression_learner.trigger_learning_for_chat()) asyncio.create_task(self.expression_learner.trigger_learning_for_chat())
asyncio.create_task(global_memory_chest.build_running_content(chat_id=self.stream_id)) asyncio.create_task(global_memory_chest.build_running_content(chat_id=self.stream_id))
asyncio.create_task(frequency_control_manager.get_or_create_frequency_control(self.stream_id).trigger_frequency_adjust())
cycle_timers, thinking_id = self.start_cycle() cycle_timers, thinking_id = self.start_cycle()

View File

@ -44,7 +44,7 @@ class HeartFCMessageReceiver:
# 2. 计算at信息 # 2. 计算at信息
is_mentioned, is_at, reply_probability_boost = is_mentioned_bot_in_message(message) is_mentioned, is_at, reply_probability_boost = is_mentioned_bot_in_message(message)
print(f"is_mentioned: {is_mentioned}, is_at: {is_at}, reply_probability_boost: {reply_probability_boost}") # print(f"is_mentioned: {is_mentioned}, is_at: {is_at}, reply_probability_boost: {reply_probability_boost}")
message.is_mentioned = is_mentioned message.is_mentioned = is_mentioned
message.is_at = is_at message.is_at = is_at
message.reply_probability_boost = reply_probability_boost message.reply_probability_boost = reply_probability_boost

View File

@ -14,8 +14,6 @@ from src.common.logger import get_logger
from src.common.data_models.info_data_model import ActionPlannerInfo from src.common.data_models.info_data_model import ActionPlannerInfo
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.chat.utils.chat_message_builder import ( from src.chat.utils.chat_message_builder import (
build_readable_actions,
get_actions_by_timestamp_with_chat,
build_readable_messages_with_id, build_readable_messages_with_id,
get_raw_msg_before_timestamp_with_chat, get_raw_msg_before_timestamp_with_chat,
) )
@ -418,7 +416,6 @@ class ActionPlanner:
return filtered_actions return filtered_actions
async def _build_action_options_block(self, current_available_actions: Dict[str, ActionInfo]) -> str: async def _build_action_options_block(self, current_available_actions: Dict[str, ActionInfo]) -> str:
# sourcery skip: use-join
"""构建动作选项块""" """构建动作选项块"""
if not current_available_actions: if not current_available_actions:
return "" return ""
@ -474,8 +471,8 @@ class ActionPlanner:
# 调用LLM # 调用LLM
llm_content, (reasoning_content, _, _) = await self.planner_llm.generate_response_async(prompt=prompt) llm_content, (reasoning_content, _, _) = await self.planner_llm.generate_response_async(prompt=prompt)
# logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}") logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}")
# logger.info(f"{self.log_prefix}规划器原始响应: {llm_content}") logger.info(f"{self.log_prefix}规划器原始响应: {llm_content}")
if global_config.debug.show_prompt: if global_config.debug.show_prompt:
logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}") logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}")

View File

@ -1,11 +1,9 @@
import time import time
import json import json
import os import os
import re
from datetime import datetime from datetime import datetime
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
import traceback import traceback
import difflib
from src.common.logger import get_logger from src.common.logger import get_logger
from src.common.database.database_model import Expression from src.common.database.database_model import Expression
from src.llm_models.utils_model import LLMRequest from src.llm_models.utils_model import LLMRequest

View File

@ -131,6 +131,8 @@ class ExpressionSelector:
# 过滤目标消息内容,移除回复、表情包等特殊格式 # 过滤目标消息内容,移除回复、表情包等特殊格式
filtered_target_message = filter_message_content(target_message) filtered_target_message = filter_message_content(target_message)
logger.info(f"{chat_id} 预测表达方式,过滤后的目标消息内容: {filtered_target_message}")
# 支持多chat_id合并预测 # 支持多chat_id合并预测
related_chat_ids = self.get_related_chat_ids(chat_id) related_chat_ids = self.get_related_chat_ids(chat_id)
@ -181,7 +183,7 @@ class ExpressionSelector:
predicted_expressions.sort(key=lambda x: x.get("prediction_score", 0.0), reverse=True) predicted_expressions.sort(key=lambda x: x.get("prediction_score", 0.0), reverse=True)
selected_expressions = predicted_expressions[:total_num] selected_expressions = predicted_expressions[:total_num]
logger.info(f"聊天室 {chat_id} 预测到 {len(selected_expressions)} 个表达方式") logger.info(f"{chat_id} 预测到 {len(selected_expressions)} 个表达方式")
return selected_expressions return selected_expressions
except Exception as e: except Exception as e:

View File

@ -1,11 +1,12 @@
from src.common.logger import get_logger from src.common.logger import get_logger
from src.chat.frequency_control.frequency_control import frequency_control_manager from src.chat.frequency_control.frequency_control import frequency_control_manager
from src.config.config import global_config
logger = get_logger("frequency_api") logger = get_logger("frequency_api")
def get_current_talk_frequency(chat_id: str) -> float: def get_current_talk_value(chat_id: str) -> float:
return frequency_control_manager.get_or_create_frequency_control(chat_id).get_talk_frequency_adjust() return frequency_control_manager.get_or_create_frequency_control(chat_id).get_talk_frequency_adjust() * global_config.chat.get_talk_value(chat_id)
def set_talk_frequency_adjust(chat_id: str, talk_frequency_adjust: float) -> None: def set_talk_frequency_adjust(chat_id: str, talk_frequency_adjust: float) -> None: