merge:合并focus和normal的planner
This commit is contained in:
@@ -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"]
|
||||||
|
|||||||
@@ -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(
|
|
||||||
chat_id=self.chat_id,
|
|
||||||
timestamp=time.time(),
|
|
||||||
limit=global_config.chat.max_context_size,
|
|
||||||
)
|
|
||||||
|
|
||||||
chat_context = 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()
|
|
||||||
|
|
||||||
# 获取聊天类型和目标信息
|
|
||||||
chat_target_info = None
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 重新获取更准确的聊天信息
|
|
||||||
is_group_chat, chat_target_info = get_chat_type_and_target_info(self.chat_id)
|
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}")
|
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处理后的最终可用动作集
|
current_available_actions_dict = self.action_manager.get_using_actions_for_mode(self.mode)
|
||||||
# 注意:动作的激活判定现在在主循环的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,
|
||||||
@@ -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()
|
|
||||||
@@ -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,专注模式:focus,auto模式:在普通模式和专注模式之间自动切换
|
||||||
auto_focus_threshold = 1 # 自动切换到专注聊天的阈值,越低越容易进入专注聊天
|
auto_focus_threshold = 1 # 自动切换到专注聊天的阈值,越低越容易进入专注聊天
|
||||||
exit_focus_threshold = 1 # 自动退出专注聊天的阈值,越低越容易退出专注聊天
|
exit_focus_threshold = 1 # 自动退出专注聊天的阈值,越低越容易退出专注聊天
|
||||||
# 普通模式下,麦麦会针对感兴趣的消息进行回复,token消耗量较低
|
# 普通模式下,麦麦会针对感兴趣的消息进行回复,token消耗量较低
|
||||||
|
|||||||
Reference in New Issue
Block a user