merge:合并focus和normal的planner

This commit is contained in:
SengokuCola
2025-07-06 21:45:40 +08:00
parent 18778d2dc7
commit 42a68a29c3
4 changed files with 67 additions and 392 deletions

View File

@@ -19,6 +19,7 @@ from src.person_info.relationship_builder_manager import relationship_builder_ma
from .priority_manager import PriorityManager from .priority_manager import PriorityManager
import traceback import traceback
from src.chat.planner_actions.planner_normal import NormalChatPlanner from src.chat.planner_actions.planner_normal import NormalChatPlanner
from src.chat.planner_actions.planner_focus import ActionPlanner
from src.chat.planner_actions.action_modifier import ActionModifier from src.chat.planner_actions.action_modifier import ActionModifier
from src.chat.utils.utils import get_chat_type_and_target_info from src.chat.utils.utils import get_chat_type_and_target_info
@@ -70,7 +71,7 @@ class NormalChat:
# Planner相关初始化 # Planner相关初始化
self.action_manager = ActionManager() self.action_manager = ActionManager()
self.planner = NormalChatPlanner(self.stream_name, self.action_manager) self.planner = ActionPlanner(self.stream_id, self.action_manager, mode="normal")
self.action_modifier = ActionModifier(self.action_manager, self.stream_id) self.action_modifier = ActionModifier(self.action_manager, self.stream_id)
self.enable_planner = global_config.normal_chat.enable_planner # 从配置中读取是否启用planner self.enable_planner = global_config.normal_chat.enable_planner # 从配置中读取是否启用planner
@@ -525,7 +526,7 @@ class NormalChat:
return no_action return no_action
# 执行规划 # 执行规划
plan_result = await self.planner.plan(message) plan_result = await self.planner.plan()
action_type = plan_result["action_result"]["action_type"] action_type = plan_result["action_result"]["action_type"]
action_data = plan_result["action_result"]["action_data"] action_data = plan_result["action_result"]["action_data"]
reasoning = plan_result["action_result"]["reasoning"] reasoning = plan_result["action_result"]["reasoning"]

View File

@@ -29,13 +29,15 @@ def init_prompt():
{chat_content_block} {chat_content_block}
{moderation_prompt} {moderation_prompt}
现在请你根据聊天内容选择合适的action: 现在请你根据{by_what}选择合适的action:
{no_action_block}
{action_options_text} {action_options_text}
你必须从上面列出的可用action中选择一个并说明原因
请根据动作示例以严格的 JSON 格式输出且仅包含 JSON 内容 请根据动作示例以严格的 JSON 格式输出且仅包含 JSON 内容
""", """,
"simple_planner_prompt", "planner_prompt",
) )
Prompt( Prompt(
@@ -52,20 +54,15 @@ def init_prompt():
class ActionPlanner: class ActionPlanner:
def __init__(self, chat_id: str, action_manager: ActionManager): def __init__(self, chat_id: str, action_manager: ActionManager, mode: str = "focus"):
self.chat_id = chat_id self.chat_id = chat_id
self.log_prefix = f"[{get_chat_manager().get_stream_name(chat_id) or chat_id}]" self.log_prefix = f"[{get_chat_manager().get_stream_name(chat_id) or chat_id}]"
self.mode = mode
self.action_manager = action_manager self.action_manager = action_manager
# LLM规划器配置 # LLM规划器配置
self.planner_llm = LLMRequest( self.planner_llm = LLMRequest(
model=global_config.model.planner, model=global_config.model.planner,
request_type="focus.planner", # 用于动作规划 request_type=f"{self.mode}.planner", # 用于动作规划
)
self.utils_llm = LLMRequest(
model=global_config.model.utils_small,
request_type="focus.planner", # 用于动作规划
) )
self.last_obs_time_mark = 0.0 self.last_obs_time_mark = 0.0
@@ -82,37 +79,10 @@ class ActionPlanner:
try: try:
is_group_chat = True is_group_chat = True
message_list_before_now = get_raw_msg_before_timestamp_with_chat( is_group_chat, chat_target_info = get_chat_type_and_target_info(self.chat_id)
chat_id=self.chat_id, logger.debug(f"{self.log_prefix}获取到聊天信息 - 群聊: {is_group_chat}, 目标信息: {chat_target_info}")
timestamp=time.time(),
limit=global_config.chat.max_context_size,
)
chat_context = build_readable_messages( current_available_actions_dict = self.action_manager.get_using_actions_for_mode(self.mode)
messages=message_list_before_now,
timestamp_mode="normal_no_YMD",
read_mark=self.last_obs_time_mark,
truncate=True,
show_actions=True,
)
self.last_obs_time_mark = time.time()
# 获取聊天类型和目标信息
chat_target_info = None
try:
# 重新获取更准确的聊天信息
is_group_chat, chat_target_info = get_chat_type_and_target_info(self.chat_id)
logger.debug(f"{self.log_prefix}获取到聊天信息 - 群聊: {is_group_chat}, 目标信息: {chat_target_info}")
except Exception as e:
logger.warning(f"{self.log_prefix}获取聊天目标信息失败: {e}")
chat_target_info = None
# 获取经过modify_actions处理后的最终可用动作集
# 注意动作的激活判定现在在主循环的modify_actions中完成
# 使用Focus模式过滤动作
current_available_actions_dict = self.action_manager.get_using_actions_for_mode("focus")
# 获取完整的动作信息 # 获取完整的动作信息
all_registered_actions = self.action_manager.get_registered_actions() all_registered_actions = self.action_manager.get_registered_actions()
@@ -130,7 +100,6 @@ class ActionPlanner:
action = "no_reply" action = "no_reply"
reasoning = "没有可用的动作" if not current_available_actions else "只有no_reply动作可用跳过规划" reasoning = "没有可用的动作" if not current_available_actions else "只有no_reply动作可用跳过规划"
logger.info(f"{self.log_prefix}{reasoning}") logger.info(f"{self.log_prefix}{reasoning}")
self.action_manager.restore_actions()
logger.debug( logger.debug(
f"{self.log_prefix}[focus]沉默后恢复到默认动作集, 当前可用: {list(self.action_manager.get_using_actions().keys())}" f"{self.log_prefix}[focus]沉默后恢复到默认动作集, 当前可用: {list(self.action_manager.get_using_actions().keys())}"
) )
@@ -142,14 +111,12 @@ class ActionPlanner:
prompt = await self.build_planner_prompt( prompt = await self.build_planner_prompt(
is_group_chat=is_group_chat, # <-- Pass HFC state is_group_chat=is_group_chat, # <-- Pass HFC state
chat_target_info=chat_target_info, # <-- 传递获取到的聊天目标信息 chat_target_info=chat_target_info, # <-- 传递获取到的聊天目标信息
observed_messages_str=chat_context, # <-- Pass local variable
current_available_actions=current_available_actions, # <-- Pass determined actions current_available_actions=current_available_actions, # <-- Pass determined actions
) )
# --- 调用 LLM (普通文本生成) --- # --- 调用 LLM (普通文本生成) ---
llm_content = None llm_content = None
try: try:
prompt = f"{prompt}"
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}")
@@ -164,34 +131,21 @@ class ActionPlanner:
if llm_content: if llm_content:
try: try:
fixed_json_string = repair_json(llm_content) parsed_json = json.loads(repair_json(llm_content))
if isinstance(fixed_json_string, str):
try:
parsed_json = json.loads(fixed_json_string)
except json.JSONDecodeError as decode_error:
logger.error(f"JSON解析错误: {str(decode_error)}")
parsed_json = {}
else:
# 如果repair_json直接返回了字典对象直接使用
parsed_json = fixed_json_string
# 处理repair_json可能返回列表的情况
if isinstance(parsed_json, list): if isinstance(parsed_json, list):
if parsed_json: if parsed_json:
# 取列表中最后一个元素(通常是最完整的)
parsed_json = parsed_json[-1] parsed_json = parsed_json[-1]
logger.warning(f"{self.log_prefix}LLM返回了多个JSON对象使用最后一个: {parsed_json}") logger.warning(f"{self.log_prefix}LLM返回了多个JSON对象使用最后一个: {parsed_json}")
else: else:
parsed_json = {} parsed_json = {}
# 确保parsed_json是字典
if not isinstance(parsed_json, dict): if not isinstance(parsed_json, dict):
logger.error(f"{self.log_prefix}解析后的JSON不是字典类型: {type(parsed_json)}") logger.error(f"{self.log_prefix}解析后的JSON不是字典类型: {type(parsed_json)}")
parsed_json = {} parsed_json = {}
# 提取决策,提供默认值 action = parsed_json.get("action", "no_reply")
extracted_action = parsed_json.get("action", "no_reply") reasoning = parsed_json.get("reasoning", "未提供原因")
extracted_reasoning = ""
# 将所有其他属性添加到action_data # 将所有其他属性添加到action_data
action_data = {} action_data = {}
@@ -199,16 +153,16 @@ class ActionPlanner:
if key not in ["action", "reasoning"]: if key not in ["action", "reasoning"]:
action_data[key] = value action_data[key] = value
if extracted_action not in current_available_actions: if action == "no_action":
action = "no_reply"
reasoning = "决定不使用额外动作"
if action not in current_available_actions and action != "no_action":
logger.warning( logger.warning(
f"{self.log_prefix}LLM 返回了当前不可用或无效的动作: '{extracted_action}' (可用: {list(current_available_actions.keys())}),将强制使用 'no_reply'" f"{self.log_prefix}LLM 返回了当前不可用或无效的动作: '{action}' (可用: {list(current_available_actions.keys())}),将强制使用 'no_reply'"
) )
action = "no_reply" action = "no_reply"
reasoning = f"LLM 返回了当前不可用的动作 '{extracted_action}' (可用: {list(current_available_actions.keys())})。原始理由: {extracted_reasoning}" reasoning = f"LLM 返回了当前不可用的动作 '{action}' (可用: {list(current_available_actions.keys())})。原始理由: {reasoning}"
else:
# 动作有效且可用
action = extracted_action
reasoning = extracted_reasoning
except Exception as json_e: except Exception as json_e:
logger.warning(f"{self.log_prefix}解析LLM响应JSON失败 {json_e}. LLM原始输出: '{llm_content}'") logger.warning(f"{self.log_prefix}解析LLM响应JSON失败 {json_e}. LLM原始输出: '{llm_content}'")
@@ -222,13 +176,19 @@ class ActionPlanner:
action = "no_reply" action = "no_reply"
reasoning = f"Planner 内部处理错误: {outer_e}" reasoning = f"Planner 内部处理错误: {outer_e}"
# 恢复到默认动作集
self.action_manager.restore_actions()
logger.debug(
f"{self.log_prefix}规划后恢复到默认动作集, 当前可用: {list(self.action_manager.get_using_actions().keys())}"
)
action_result = {"action_type": action, "action_data": action_data, "reasoning": reasoning} is_parallel = False
if action in current_available_actions:
action_info = current_available_actions[action]
is_parallel = action_info.get("parallel_action", False)
action_result = {
"action_type": action,
"action_data": action_data,
"reasoning": reasoning,
"timestamp": time.time(),
"is_parallel": is_parallel,
}
plan_result = { plan_result = {
"action_result": action_result, "action_result": action_result,
@@ -241,11 +201,36 @@ class ActionPlanner:
self, self,
is_group_chat: bool, # Now passed as argument is_group_chat: bool, # Now passed as argument
chat_target_info: Optional[dict], # Now passed as argument chat_target_info: Optional[dict], # Now passed as argument
observed_messages_str: str,
current_available_actions, current_available_actions,
) -> str: ) -> str:
"""构建 Planner LLM 的提示词 (获取模板并填充数据)""" """构建 Planner LLM 的提示词 (获取模板并填充数据)"""
try: try:
message_list_before_now = get_raw_msg_before_timestamp_with_chat(
chat_id=self.chat_id,
timestamp=time.time(),
limit=global_config.chat.max_context_size,
)
chat_content_block = build_readable_messages(
messages=message_list_before_now,
timestamp_mode="normal_no_YMD",
read_mark=self.last_obs_time_mark,
truncate=True,
show_actions=True,
)
self.last_obs_time_mark = time.time()
if self.mode == "focus":
by_what = "聊天内容"
no_action_block = ""
else:
by_what = "聊天内容和用户的最新消息"
no_action_block = """重要说明:
- 'no_action' 表示只进行普通聊天回复不执行任何额外动作
- 其他action表示在普通回复的基础上执行相应的额外动作"""
chat_context_description = "你现在正在一个群聊中" chat_context_description = "你现在正在一个群聊中"
chat_target_name = None # Only relevant for private chat_target_name = None # Only relevant for private
if not is_group_chat and chat_target_info: if not is_group_chat and chat_target_info:
@@ -254,11 +239,6 @@ class ActionPlanner:
) )
chat_context_description = f"你正在和 {chat_target_name} 私聊" chat_context_description = f"你正在和 {chat_target_name} 私聊"
chat_content_block = ""
if observed_messages_str:
chat_content_block = f"\n{observed_messages_str}"
else:
chat_content_block = "你还未开始聊天"
action_options_block = "" action_options_block = ""
@@ -286,10 +266,8 @@ class ActionPlanner:
action_options_block += using_action_prompt action_options_block += using_action_prompt
# moderation_prompt_block = "请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。" moderation_prompt_block = "请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。"
moderation_prompt_block = ""
# 获取当前时间
time_block = f"当前时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" time_block = f"当前时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
bot_name = global_config.bot.nickname bot_name = global_config.bot.nickname
@@ -300,11 +278,13 @@ class ActionPlanner:
bot_core_personality = global_config.personality.personality_core bot_core_personality = global_config.personality.personality_core
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{bot_core_personality}" indentify_block = f"你的名字是{bot_name}{bot_nickname},你{bot_core_personality}"
planner_prompt_template = await global_prompt_manager.get_prompt_async("simple_planner_prompt") planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt")
prompt = planner_prompt_template.format( prompt = planner_prompt_template.format(
time_block=time_block, time_block=time_block,
by_what=by_what,
chat_context_description=chat_context_description, chat_context_description=chat_context_description,
chat_content_block=chat_content_block, chat_content_block=chat_content_block,
no_action_block=no_action_block,
action_options_text=action_options_block, action_options_text=action_options_block,
moderation_prompt=moderation_prompt_block, moderation_prompt=moderation_prompt_block,
indentify_block=indentify_block, indentify_block=indentify_block,

View File

@@ -1,306 +0,0 @@
import json
from typing import Dict, Any
from rich.traceback import install
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.individuality.individuality import get_individuality
from src.chat.planner_actions.action_manager import ActionManager
from src.chat.message_receive.message import MessageThinking
from json_repair import repair_json
from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat
import time
import traceback
logger = get_logger("normal_chat_planner")
install(extra_lines=3)
def init_prompt():
Prompt(
"""
你的自我认知是:
{self_info_block}
请记住你的性格,身份和特点。
你是群内的一员,你现在正在参与群内的闲聊,以下是群内的聊天内容:
{chat_context}
基于以上聊天上下文和用户的最新消息选择最合适的action。
注意除了下面动作选项之外你在聊天中不能做其他任何事情这是你能力的边界现在请你选择合适的action:
{action_options_text}
重要说明:
- "no_action" 表示只进行普通聊天回复,不执行任何额外动作
- 其他action表示在普通回复的基础上执行相应的额外动作
你必须从上面列出的可用action中选择一个并说明原因。
{moderation_prompt}
请以动作的输出要求,以严格的 JSON 格式输出,且仅包含 JSON 内容。不要有任何其他文字或解释:
""",
"normal_chat_planner_prompt",
)
Prompt(
"""
动作:{action_name}
动作描述:{action_description}
{action_require}
{{
"action": "{action_name}",{action_parameters}
}}
""",
"normal_chat_action_prompt",
)
class NormalChatPlanner:
def __init__(self, log_prefix: str, action_manager: ActionManager):
self.log_prefix = log_prefix
# LLM规划器配置
self.planner_llm = LLMRequest(
model=global_config.model.planner,
request_type="normal.planner", # 用于normal_chat动作规划
)
self.action_manager = action_manager
async def plan(self, message: MessageThinking) -> Dict[str, Any]:
"""
Normal Chat 规划器: 使用LLM根据上下文决定做出什么动作。
参数:
message: 思考消息对象
sender_name: 发送者名称
"""
action = "no_action" # 默认动作改为no_action
reasoning = "规划器初始化默认"
action_data = {}
try:
# 设置默认值
nickname_str = ""
for nicknames in global_config.bot.alias_names:
nickname_str += f"{nicknames},"
name_block = f"你的名字是{global_config.bot.nickname},你的昵称有{nickname_str},有人也会用这些昵称称呼你。"
personality_block = get_individuality().get_personality_prompt(x_person=2, level=2)
identity_block = get_individuality().get_identity_prompt(x_person=2, level=2)
self_info = name_block + personality_block + identity_block
# 获取当前可用的动作使用Normal模式过滤
current_available_actions = self.action_manager.get_using_actions_for_mode("normal")
# 注意:动作的激活判定现在在 normal_chat_action_modifier 中完成
# 这里直接使用经过 action_modifier 处理后的最终动作集
# 符合职责分离原则ActionModifier负责动作管理Planner专注于决策
# 如果没有可用动作直接返回no_action
if not current_available_actions:
logger.debug(f"{self.log_prefix}规划器: 没有可用动作返回no_action")
return {
"action_result": {
"action_type": action,
"action_data": action_data,
"reasoning": reasoning,
"is_parallel": True,
},
"chat_context": "",
"action_prompt": "",
}
# 构建normal_chat的上下文 (使用与normal_chat相同的prompt构建方法)
message_list_before_now = get_raw_msg_before_timestamp_with_chat(
chat_id=message.chat_stream.stream_id,
timestamp=time.time(),
limit=global_config.chat.max_context_size,
)
chat_context = build_readable_messages(
message_list_before_now,
replace_bot_name=True,
merge_messages=False,
timestamp_mode="relative",
read_mark=0.0,
show_actions=True,
)
# 构建planner的prompt
prompt = await self.build_planner_prompt(
self_info_block=self_info,
chat_context=chat_context,
current_available_actions=current_available_actions,
)
if not prompt:
logger.warning(f"{self.log_prefix}规划器: 构建提示词失败")
return {
"action_result": {
"action_type": action,
"action_data": action_data,
"reasoning": reasoning,
"is_parallel": False,
},
"chat_context": chat_context,
"action_prompt": "",
}
# 使用LLM生成动作决策
try:
content, (reasoning_content, model_name) = await self.planner_llm.generate_response_async(prompt)
logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}")
logger.info(f"{self.log_prefix}规划器原始响应: {content}")
if reasoning_content:
logger.info(f"{self.log_prefix}规划器推理: {reasoning_content}")
# 解析JSON响应
try:
# 尝试修复JSON
fixed_json = repair_json(content)
action_result = json.loads(fixed_json)
action = action_result.get("action", "no_action")
reasoning = action_result.get("reasoning", "未提供原因")
# 提取其他参数作为action_data
action_data = {k: v for k, v in action_result.items() if k not in ["action", "reasoning"]}
# 验证动作是否在可用动作列表中,或者是特殊动作
if action not in current_available_actions:
logger.warning(f"{self.log_prefix}规划器选择了不可用的动作: {action}, 回退到no_action")
action = "no_action"
reasoning = f"选择的动作{action}不在可用列表中回退到no_action"
action_data = {}
except json.JSONDecodeError as e:
logger.warning(f"{self.log_prefix}规划器JSON解析失败: {e}, 内容: {content}")
action = "no_action"
reasoning = "JSON解析失败使用默认动作"
action_data = {}
except Exception as e:
logger.error(f"{self.log_prefix}规划器LLM调用失败: {e}")
action = "no_action"
reasoning = "LLM调用失败使用默认动作"
action_data = {}
except Exception as outer_e:
logger.error(f"{self.log_prefix}规划器异常: {outer_e}")
# 设置异常时的默认值
current_available_actions = {}
chat_context = "无法获取聊天上下文"
prompt = ""
action = "no_action"
reasoning = "规划器出现异常,使用默认动作"
action_data = {}
# 检查动作是否支持并行执行
is_parallel = False
if action in current_available_actions:
action_info = current_available_actions[action]
is_parallel = action_info.get("parallel_action", False)
logger.debug(
f"{self.log_prefix}规划器决策动作:{action}, 动作信息: '{action_data}', 理由: {reasoning}, 并行执行: {is_parallel}"
)
# 恢复到默认动作集
self.action_manager.restore_actions()
logger.debug(
f"{self.log_prefix}规划后恢复到默认动作集, 当前可用: {list(self.action_manager.get_using_actions().keys())}"
)
# 构建 action 记录
action_record = {
"action_type": action,
"action_data": action_data,
"reasoning": reasoning,
"timestamp": time.time(),
"model_name": model_name if "model_name" in locals() else None,
}
action_result = {
"action_type": action,
"action_data": action_data,
"reasoning": reasoning,
"is_parallel": is_parallel,
"action_record": json.dumps(action_record, ensure_ascii=False),
}
plan_result = {
"action_result": action_result,
"chat_context": chat_context,
"action_prompt": prompt,
}
return plan_result
async def build_planner_prompt(
self,
self_info_block: str,
chat_context: str,
current_available_actions: Dict[str, Any],
) -> str:
"""构建 Normal Chat Planner LLM 的提示词"""
try:
# 构建动作选项文本
action_options_text = ""
for action_name, action_info in current_available_actions.items():
action_description = action_info.get("description", "")
action_parameters = action_info.get("parameters", {})
action_require = action_info.get("require", [])
if action_parameters:
param_text = "\n"
# print(action_parameters)
for param_name, param_description in action_parameters.items():
param_text += f' "{param_name}":"{param_description}"\n'
param_text = param_text.rstrip("\n")
else:
param_text = ""
require_text = ""
for require_item in action_require:
require_text += f"- {require_item}\n"
require_text = require_text.rstrip("\n")
# 构建单个动作的提示
action_prompt = await global_prompt_manager.format_prompt(
"normal_chat_action_prompt",
action_name=action_name,
action_description=action_description,
action_parameters=param_text,
action_require=require_text,
)
action_options_text += action_prompt + "\n\n"
# 审核提示
moderation_prompt = "请确保你的回复符合平台规则,避免不当内容。"
# 使用模板构建最终提示词
prompt = await global_prompt_manager.format_prompt(
"normal_chat_planner_prompt",
self_info_block=self_info_block,
action_options_text=action_options_text,
moderation_prompt=moderation_prompt,
chat_context=chat_context,
)
return prompt
except Exception as e:
logger.error(f"{self.log_prefix}构建Planner提示词失败: {e}")
traceback.print_exc()
return ""
init_prompt()

View File

@@ -61,7 +61,7 @@ enable_relationship = true # 是否启用关系系统
relation_frequency = 1 # 关系频率麦麦构建关系的速度仅在normal_chat模式下有效 relation_frequency = 1 # 关系频率麦麦构建关系的速度仅在normal_chat模式下有效
[chat] #麦麦的聊天通用设置 [chat] #麦麦的聊天通用设置
chat_mode = "normal" # 聊天模式 —— 普通模式normal专注模式focus在普通模式和专注模式之间自动切换 chat_mode = "normal" # 聊天模式 —— 普通模式normal专注模式focusauto模式在普通模式和专注模式之间自动切换
auto_focus_threshold = 1 # 自动切换到专注聊天的阈值,越低越容易进入专注聊天 auto_focus_threshold = 1 # 自动切换到专注聊天的阈值,越低越容易进入专注聊天
exit_focus_threshold = 1 # 自动退出专注聊天的阈值,越低越容易退出专注聊天 exit_focus_threshold = 1 # 自动退出专注聊天的阈值,越低越容易退出专注聊天
# 普通模式下麦麦会针对感兴趣的消息进行回复token消耗量较低 # 普通模式下麦麦会针对感兴趣的消息进行回复token消耗量较低