improvcve:修改normal下的planner prompt

This commit is contained in:
SengokuCola
2025-08-23 11:54:22 +08:00
parent add05cee55
commit 0a70de9444
4 changed files with 109 additions and 93 deletions

View File

@@ -448,7 +448,7 @@ class HeartFChatting:
prompt_info = await self.action_planner.build_planner_prompt( prompt_info = await self.action_planner.build_planner_prompt(
is_group_chat=planner_info[0], is_group_chat=planner_info[0],
chat_target_info=planner_info[1], chat_target_info=planner_info[1],
current_available_actions=planner_info[2], # current_available_actions=planner_info[2],
chat_content_block=chat_content_block, chat_content_block=chat_content_block,
actions_before_now_block=actions_before_now_block, actions_before_now_block=actions_before_now_block,
message_id_list=message_id_list, message_id_list=message_id_list,

View File

@@ -47,7 +47,14 @@ def init_prompt():
现在请你根据聊天内容和用户的最新消息选择合适的action和触发action的消息: 现在请你根据聊天内容和用户的最新消息选择合适的action和触发action的消息:
{actions_before_now_block} {actions_before_now_block}
{no_action_block} 动作:no_action
动作描述:不进行动作,等待合适的时机
- 当你刚刚发送了消息没有人回复时选择no_action
- 当你一次发送了太多消息,为了避免过于烦人,可以不回复
{{
"action": "no_action",
"reason":"不动作的原因"
}}
动作reply 动作reply
动作描述:参与聊天回复,发送文本进行表达 动作描述:参与聊天回复,发送文本进行表达
@@ -61,14 +68,42 @@ def init_prompt():
"reason":"回复的原因" "reason":"回复的原因"
}} }}
{action_options_text}
你必须从上面列出的可用action中选择一个并说明触发action的消息id不是消息原文和选择该action的原因。消息id格式:m+数字 你必须从上面列出的可用action中选择一个并说明触发action的消息id不是消息原文和选择该action的原因。消息id格式:m+数字
请根据动作示例,以严格的 JSON 格式输出,且仅包含 JSON 内容: 请根据动作示例,以严格的 JSON 格式输出,且仅包含 JSON 内容:
""", """,
"planner_prompt", "planner_prompt",
) )
Prompt(
"""
{time_block}
{name_block}
{chat_context_description},以下是具体的聊天内容
{chat_content_block}
{moderation_prompt}
现在,最新的聊天消息引起了你的兴趣,你想要对其中的消息进行回复,回复标准如下:
- 你想要闲聊或者随便附和
- 有人提到了你,但是你还没有回应
- {mentioned_bonus}
- 如果你刚刚进行了回复,不要对同一个话题重复回应
请你选中一条需要回复的消息并输出其id,输出格式如下:
{{
"action": "reply",
"target_message_id":"想要回复的消息id消息id格式:m+数字",
"reason":"回复的原因"
}}
请根据示例,以严格的 JSON 格式输出,且仅包含 JSON 内容:
""",
"planner_reply_prompt",
)
Prompt( Prompt(
""" """
@@ -87,15 +122,12 @@ def init_prompt():
Prompt( Prompt(
""" """
{time_block}
{name_block} {name_block}
请你根据聊天内容选择一个或多个action来参与聊天。如果没有合适的action请选择no_action。
{chat_context_description}以下是具体的聊天内容 {chat_context_description}{time_block}现在请你根据以下聊天内容选择一个或多个action来参与聊天。如果没有合适的action请选择no_action。,
{chat_content_block} {chat_content_block}
{moderation_prompt} {moderation_prompt}
现在请你根据聊天内容和用户的最新消息选择合适的action和触发action的消息: 现在请你根据聊天内容和用户的最新消息选择合适的action和触发action的消息:
{actions_before_now_block} {actions_before_now_block}
@@ -108,7 +140,6 @@ no_action不选择任何动作
{action_options_text} {action_options_text}
请选择并说明触发action的消息id和选择该action的原因。消息id格式:m+数字 请选择并说明触发action的消息id和选择该action的原因。消息id格式:m+数字
请根据动作示例,以严格的 JSON 格式输出,且仅包含 JSON 内容: 请根据动作示例,以严格的 JSON 格式输出,且仅包含 JSON 内容:
""", """,
"sub_planner_prompt", "sub_planner_prompt",
@@ -151,18 +182,6 @@ class ActionPlanner:
if item[0] == message_id: if item[0] == message_id:
return item[1] return item[1]
return None return None
def get_latest_message(self, message_id_list: List[DatabaseMessages]) -> Optional[DatabaseMessages]:
"""
获取消息列表中的最新消息
Args:
message_id_list: 消息ID列表格式为[{'id': str, 'message': dict}, ...]
Returns:
最新的消息字典如果列表为空则返回None
"""
return message_id_list[-1] if message_id_list else None
def _parse_single_action(self, action_json: dict, message_id_list: List[Tuple[str, DatabaseMessages]], current_available_actions: List[Tuple[str, ActionInfo]]) -> List[ActionPlannerInfo]: def _parse_single_action(self, action_json: dict, message_id_list: List[Tuple[str, DatabaseMessages]], current_available_actions: List[Tuple[str, ActionInfo]]) -> List[ActionPlannerInfo]:
"""解析单个action JSON并返回ActionPlannerInfo列表""" """解析单个action JSON并返回ActionPlannerInfo列表"""
@@ -187,7 +206,7 @@ class ActionPlanner:
if target_message is None: if target_message is None:
logger.warning(f"{self.log_prefix}无法找到target_message_id '{target_message_id}' 对应的消息") logger.warning(f"{self.log_prefix}无法找到target_message_id '{target_message_id}' 对应的消息")
# 选择最新消息作为target_message # 选择最新消息作为target_message
target_message = self.get_latest_message(message_id_list) target_message = message_id_list[-1]
else: else:
logger.warning(f"{self.log_prefix}动作'{action}'缺少target_message_id") logger.warning(f"{self.log_prefix}动作'{action}'缺少target_message_id")
@@ -242,15 +261,14 @@ class ActionPlanner:
action_names_in_list = [name for name, _ in action_list] action_names_in_list = [name for name, _ in action_list]
# actions_before_now是List[Dict[str, Any]]格式需要提取action_type字段 # actions_before_now是List[Dict[str, Any]]格式需要提取action_type字段
filtered_actions = [] filtered_actions = []
# print(actions_before_now)
# print(action_names_in_list)
for action_record in actions_before_now: for action_record in actions_before_now:
if isinstance(action_record, dict) and 'action_name' in action_record: # print(action_record)
action_type = action_record['action_name'] # print(action_record['action_name'])
if action_type in action_names_in_list: # print(action_names_in_list)
filtered_actions.append(action_record) action_type = action_record['action_name']
if action_type in action_names_in_list:
filtered_actions.append(action_record)
actions_before_now_block = build_readable_actions( actions_before_now_block = build_readable_actions(
actions=filtered_actions, actions=filtered_actions,
@@ -467,7 +485,7 @@ class ActionPlanner:
chat_id=self.chat_id, chat_id=self.chat_id,
timestamp_start=time.time() - 600, timestamp_start=time.time() - 600,
timestamp_end=time.time(), timestamp_end=time.time(),
limit=5, limit=6,
) )
actions_before_now_block = build_readable_actions( actions_before_now_block = build_readable_actions(
@@ -475,7 +493,7 @@ class ActionPlanner:
) )
message_list_before_now_short = message_list_before_now[:5] message_list_before_now_short = message_list_before_now[-int(global_config.chat.max_context_size * 0.3):]
chat_content_block_short, message_id_list_short = build_readable_messages_with_id( chat_content_block_short, message_id_list_short = build_readable_messages_with_id(
messages=message_list_before_now_short, messages=message_list_before_now_short,
@@ -582,7 +600,7 @@ class ActionPlanner:
prompt, message_id_list = await self.build_planner_prompt( prompt, message_id_list = 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, # <-- 传递获取到的聊天目标信息
current_available_actions="", # <-- Pass determined actions # current_available_actions="", # <-- Pass determined actions
mode=mode, mode=mode,
chat_content_block=chat_content_block, chat_content_block=chat_content_block,
actions_before_now_block=actions_before_now_block, actions_before_now_block=actions_before_now_block,
@@ -642,7 +660,7 @@ class ActionPlanner:
# 处理target_message为None的情况保持原有的重试逻辑 # 处理target_message为None的情况保持原有的重试逻辑
if target_message is None and action != "no_action": if target_message is None and action != "no_action":
# 尝试获取最新消息作为target_message # 尝试获取最新消息作为target_message
target_message = self.get_latest_message(message_id_list) target_message = message_id_list[-1]
if target_message is None: if target_message is None:
logger.warning(f"{self.log_prefix}无法获取任何消息作为target_message") logger.warning(f"{self.log_prefix}无法获取任何消息作为target_message")
else: else:
@@ -740,7 +758,7 @@ 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
current_available_actions: Dict[str, ActionInfo], # current_available_actions: Dict[str, ActionInfo],
mode: ChatMode = ChatMode.FOCUS, mode: ChatMode = ChatMode.FOCUS,
actions_before_now_block :str = "", actions_before_now_block :str = "",
chat_content_block :str = "", chat_content_block :str = "",
@@ -760,22 +778,6 @@ class ActionPlanner:
if global_config.chat.at_bot_inevitable_reply: if global_config.chat.at_bot_inevitable_reply:
mentioned_bonus = "\n- 有人提到你或者at你" mentioned_bonus = "\n- 有人提到你或者at你"
if mode == ChatMode.FOCUS:
no_action_block = """
动作no_action
动作描述:不进行动作,等待合适的时机
- 当你刚刚发送了消息没有人回复时选择no_action
- 当你一次发送了太多消息,为了避免过于烦人,可以不回复
{
"action": "no_action",
"reason":"不动作的原因"
}
"""
else:
no_action_block = """重要说明:
- 'reply' 表示只进行普通聊天回复,不执行任何额外动作
- 其他action表示在普通回复的基础上执行相应的额外动作
"""
chat_context_description = "你现在正在一个群聊中" chat_context_description = "你现在正在一个群聊中"
chat_target_name = None chat_target_name = None
@@ -784,35 +786,38 @@ class ActionPlanner:
chat_target_info.get("person_name") or chat_target_info.get("user_nickname") or "对方" chat_target_info.get("person_name") or chat_target_info.get("user_nickname") or "对方"
) )
chat_context_description = f"你正在和 {chat_target_name} 私聊" chat_context_description = f"你正在和 {chat_target_name} 私聊"
# 别删之后可能会允许主Planner扩展
action_options_block = "" # action_options_block = ""
if current_available_actions: # if current_available_actions:
for using_actions_name, using_actions_info in current_available_actions.items(): # for using_actions_name, using_actions_info in current_available_actions.items():
if using_actions_info.action_parameters: # if using_actions_info.action_parameters:
param_text = "\n" # param_text = "\n"
for param_name, param_description in using_actions_info.action_parameters.items(): # for param_name, param_description in using_actions_info.action_parameters.items():
param_text += f' "{param_name}":"{param_description}"\n' # param_text += f' "{param_name}":"{param_description}"\n'
param_text = param_text.rstrip("\n") # param_text = param_text.rstrip("\n")
else: # else:
param_text = "" # param_text = ""
require_text = "" # require_text = ""
for require_item in using_actions_info.action_require: # for require_item in using_actions_info.action_require:
require_text += f"- {require_item}\n" # require_text += f"- {require_item}\n"
require_text = require_text.rstrip("\n") # require_text = require_text.rstrip("\n")
using_action_prompt = await global_prompt_manager.get_prompt_async("action_prompt") # using_action_prompt = await global_prompt_manager.get_prompt_async("action_prompt")
using_action_prompt = using_action_prompt.format( # using_action_prompt = using_action_prompt.format(
action_name=using_actions_name, # action_name=using_actions_name,
action_description=using_actions_info.description, # action_description=using_actions_info.description,
action_parameters=param_text, # action_parameters=param_text,
action_require=require_text, # action_require=require_text,
) # )
action_options_block += using_action_prompt # action_options_block += using_action_prompt
else: # else:
action_options_block = "" # action_options_block = ""
moderation_prompt_block = "请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。" moderation_prompt_block = "请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。"
@@ -825,20 +830,31 @@ class ActionPlanner:
bot_nickname = "" bot_nickname = ""
name_block = f"你的名字是{bot_name}{bot_nickname},请注意哪些是你自己的发言。" name_block = f"你的名字是{bot_name}{bot_nickname},请注意哪些是你自己的发言。"
planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt") if mode == ChatMode.FOCUS:
prompt = planner_prompt_template.format( planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt")
time_block=time_block, prompt = planner_prompt_template.format(
chat_context_description=chat_context_description, time_block=time_block,
chat_content_block=chat_content_block, chat_context_description=chat_context_description,
actions_before_now_block=actions_before_now_block, chat_content_block=chat_content_block,
no_action_block=no_action_block, actions_before_now_block=actions_before_now_block,
mentioned_bonus=mentioned_bonus, mentioned_bonus=mentioned_bonus,
action_options_text=action_options_block, # action_options_text=action_options_block,
moderation_prompt=moderation_prompt_block, moderation_prompt=moderation_prompt_block,
name_block=name_block, name_block=name_block,
plan_style=global_config.personality.plan_style, plan_style=global_config.personality.plan_style,
) )
return prompt, message_id_list return prompt, message_id_list
else:
planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_reply_prompt")
prompt = planner_prompt_template.format(
time_block=time_block,
chat_context_description=chat_context_description,
chat_content_block=chat_content_block,
mentioned_bonus=mentioned_bonus,
moderation_prompt=moderation_prompt_block,
name_block=name_block,
)
return prompt, message_id_list
except Exception as e: except Exception as e:
logger.error(f"构建 Planner 提示词时出错: {e}") logger.error(f"构建 Planner 提示词时出错: {e}")
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())

View File

@@ -76,15 +76,15 @@ class BaseAction(ABC):
self.action_require: list[str] = getattr(self.__class__, "action_require", []).copy() self.action_require: list[str] = getattr(self.__class__, "action_require", []).copy()
# 设置激活类型实例属性(从类属性复制,提供默认值) # 设置激活类型实例属性(从类属性复制,提供默认值)
self.focus_activation_type = getattr(self.__class__, "focus_activation_type", ActionActivationType.ALWAYS) self.focus_activation_type = getattr(self.__class__, "focus_activation_type", ActionActivationType.ALWAYS) #已弃用
"""FOCUS模式下的激活类型""" """FOCUS模式下的激活类型"""
self.normal_activation_type = getattr(self.__class__, "normal_activation_type", ActionActivationType.ALWAYS) self.normal_activation_type = getattr(self.__class__, "normal_activation_type", ActionActivationType.ALWAYS) #已弃用
"""NORMAL模式下的激活类型""" """NORMAL模式下的激活类型"""
self.activation_type = getattr(self.__class__, "activation_type", self.focus_activation_type) self.activation_type = getattr(self.__class__, "activation_type", self.focus_activation_type)
"""激活类型""" """激活类型"""
self.random_activation_probability: float = getattr(self.__class__, "random_activation_probability", 0.0) self.random_activation_probability: float = getattr(self.__class__, "random_activation_probability", 0.0)
"""当激活类型为RANDOM时的概率""" """当激活类型为RANDOM时的概率"""
self.llm_judge_prompt: str = getattr(self.__class__, "llm_judge_prompt", "") self.llm_judge_prompt: str = getattr(self.__class__, "llm_judge_prompt", "") #已弃用
"""协助LLM进行判断的Prompt""" """协助LLM进行判断的Prompt"""
self.activation_keywords: list[str] = getattr(self.__class__, "activation_keywords", []).copy() self.activation_keywords: list[str] = getattr(self.__class__, "activation_keywords", []).copy()
"""激活类型为KEYWORD时的KEYWORDS列表""" """激活类型为KEYWORD时的KEYWORDS列表"""

View File

@@ -67,7 +67,7 @@ max_context_size = 20 # 上下文长度
interest_rate_mode = "fast" #激活值计算模式可选fast或者accurate interest_rate_mode = "fast" #激活值计算模式可选fast或者accurate
planner_size = 2 # 副规划器大小越小麦麦的动作执行能力越精细但是消耗更多token调大可以缓解429类错误 planner_size = 2.5 # 副规划器大小越小麦麦的动作执行能力越精细但是消耗更多token调大可以缓解429类错误
mentioned_bot_inevitable_reply = true # 提及 bot 大概率回复 mentioned_bot_inevitable_reply = true # 提及 bot 大概率回复
at_bot_inevitable_reply = true # @bot 或 提及bot 大概率回复 at_bot_inevitable_reply = true # @bot 或 提及bot 大概率回复