不再进行action_info转换了,保持一致性

This commit is contained in:
UnCLAS-Prommer
2025-07-11 00:59:49 +08:00
parent ab61b1bb22
commit 968eb92107
13 changed files with 137 additions and 151 deletions

3
.gitignore vendored
View File

@@ -316,4 +316,5 @@ run_pet.bat
!/plugins/hello_world_plugin !/plugins/hello_world_plugin
!/plugins/take_picture_plugin !/plugins/take_picture_plugin
config.toml config.toml
备忘录.txt

View File

@@ -2,14 +2,14 @@ import asyncio
import time import time
import traceback import traceback
from random import random from random import random
from typing import List, Optional from typing import List, Optional, Dict
from maim_message import UserInfo, Seg from maim_message import UserInfo, Seg
from src.config.config import global_config from src.config.config import global_config
from src.common.logger import get_logger from src.common.logger import get_logger
from src.common.message_repository import count_messages from src.common.message_repository import count_messages
from src.plugin_system.apis import generator_api from src.plugin_system.apis import generator_api
from src.plugin_system.base.component_types import ChatMode from src.plugin_system.base.component_types import ChatMode, ActionInfo
from src.chat.message_receive.chat_stream import ChatStream, get_chat_manager from src.chat.message_receive.chat_stream import ChatStream, get_chat_manager
from src.chat.message_receive.message import MessageSending, MessageRecv, MessageThinking, MessageSet from src.chat.message_receive.message import MessageSending, MessageRecv, MessageThinking, MessageSet
from src.chat.message_receive.normal_message_sender import message_manager from src.chat.message_receive.normal_message_sender import message_manager
@@ -175,12 +175,12 @@ class NormalChat:
# 改为实例方法 # 改为实例方法
async def _create_thinking_message(self, message: MessageRecv, timestamp: Optional[float] = None) -> str: async def _create_thinking_message(self, message: MessageRecv, timestamp: Optional[float] = None) -> str:
"""创建思考消息""" """创建思考消息"""
messageinfo = message.message_info message_info = message.message_info
bot_user_info = UserInfo( bot_user_info = UserInfo(
user_id=global_config.bot.qq_account, user_id=global_config.bot.qq_account,
user_nickname=global_config.bot.nickname, user_nickname=global_config.bot.nickname,
platform=messageinfo.platform, platform=message_info.platform,
) )
thinking_time_point = round(time.time(), 2) thinking_time_point = round(time.time(), 2)
@@ -456,7 +456,7 @@ class NormalChat:
willing_manager.delete(message.message_info.message_id) willing_manager.delete(message.message_info.message_id)
async def _generate_normal_response( async def _generate_normal_response(
self, message: MessageRecv, available_actions: Optional[list] self, message: MessageRecv, available_actions: Optional[Dict[str, ActionInfo]]
) -> Optional[list]: ) -> Optional[list]:
"""生成普通回复""" """生成普通回复"""
try: try:

View File

@@ -59,32 +59,11 @@ class ActionManager:
logger.debug(f"Action组件 {action_name} 已存在,跳过") logger.debug(f"Action组件 {action_name} 已存在,跳过")
continue continue
# 将插件系统的ActionInfo转换为ActionManager格式 self._registered_actions[action_name] = action_info
converted_action_info = {
"description": action_info.description,
"parameters": getattr(action_info, "action_parameters", {}),
"require": getattr(action_info, "action_require", []),
"associated_types": getattr(action_info, "associated_types", []),
"enable_plugin": action_info.enabled,
# 激活类型相关
"focus_activation_type": action_info.focus_activation_type.value,
"normal_activation_type": action_info.normal_activation_type.value,
"random_activation_probability": action_info.random_activation_probability,
"llm_judge_prompt": action_info.llm_judge_prompt,
"activation_keywords": action_info.activation_keywords,
"keyword_case_sensitive": action_info.keyword_case_sensitive,
# 模式和并行设置
"mode_enable": action_info.mode_enable,
"parallel_action": action_info.parallel_action,
# 插件信息
"_plugin_name": getattr(action_info, "plugin_name", ""),
}
self._registered_actions[action_name] = converted_action_info
# 如果启用,也添加到默认动作集 # 如果启用,也添加到默认动作集
if action_info.enabled: if action_info.enabled:
self._default_actions[action_name] = converted_action_info self._default_actions[action_name] = action_info
logger.debug( logger.debug(
f"从插件系统加载Action组件: {action_name} (插件: {getattr(action_info, 'plugin_name', 'unknown')})" f"从插件系统加载Action组件: {action_name} (插件: {getattr(action_info, 'plugin_name', 'unknown')})"
@@ -188,7 +167,7 @@ class ActionManager:
enabled_actions = {} enabled_actions = {}
for action_name, action_info in self._using_actions.items(): for action_name, action_info in self._using_actions.items():
action_mode = action_info["mode_enable"] action_mode = action_info.mode_enable
# 检查动作是否在当前模式下启用 # 检查动作是否在当前模式下启用
if action_mode in [ChatMode.ALL, mode]: if action_mode in [ChatMode.ALL, mode]:

View File

@@ -11,7 +11,7 @@ from src.chat.focus_chat.focus_loop_info import FocusLoopInfo
from src.chat.message_receive.chat_stream import get_chat_manager, ChatMessageContext from src.chat.message_receive.chat_stream import get_chat_manager, ChatMessageContext
from src.chat.planner_actions.action_manager import ActionManager from src.chat.planner_actions.action_manager import ActionManager
from src.chat.utils.chat_message_builder import get_raw_msg_before_timestamp_with_chat, build_readable_messages from src.chat.utils.chat_message_builder import get_raw_msg_before_timestamp_with_chat, build_readable_messages
from src.plugin_system.base.component_types import ChatMode, ActionInfo from src.plugin_system.base.component_types import ChatMode, ActionInfo, ActionActivationType
logger = get_logger("action_manager") logger = get_logger("action_manager")
@@ -131,9 +131,9 @@ class ActionModifier:
def _check_action_associated_types(self, all_actions: Dict[str, ActionInfo], chat_context: ChatMessageContext): def _check_action_associated_types(self, all_actions: Dict[str, ActionInfo], chat_context: ChatMessageContext):
type_mismatched_actions = [] type_mismatched_actions = []
for action_name, data in all_actions.items(): for action_name, action_info in all_actions.items():
if data["associated_types"] and not chat_context.check_types(data["associated_types"]): if action_info.associated_types and not chat_context.check_types(action_info.associated_types):
associated_types_str = ", ".join(data["associated_types"]) associated_types_str = ", ".join(action_info.associated_types)
reason = f"适配器不支持(需要: {associated_types_str}" reason = f"适配器不支持(需要: {associated_types_str}"
type_mismatched_actions.append((action_name, reason)) type_mismatched_actions.append((action_name, reason))
logger.debug(f"{self.log_prefix}决定移除动作: {action_name},原因: {reason}") logger.debug(f"{self.log_prefix}决定移除动作: {action_name},原因: {reason}")
@@ -141,7 +141,7 @@ class ActionModifier:
async def _get_deactivated_actions_by_type( async def _get_deactivated_actions_by_type(
self, self,
actions_with_info: Dict[str, Any], actions_with_info: Dict[str, ActionInfo],
mode: str = "focus", mode: str = "focus",
chat_content: str = "", chat_content: str = "",
) -> List[tuple[str, str]]: ) -> List[tuple[str, str]]:
@@ -164,27 +164,26 @@ class ActionModifier:
random.shuffle(actions_to_check) random.shuffle(actions_to_check)
for action_name, action_info in actions_to_check: for action_name, action_info in actions_to_check:
activation_type = f"{mode}_activation_type" mode_activation_type = f"{mode}_activation_type"
activation_type = action_info.get(activation_type, "always") activation_type = getattr(action_info, mode_activation_type, ActionActivationType.ALWAYS)
if activation_type == ActionActivationType.ALWAYS:
if activation_type == "always":
continue # 总是激活,无需处理 continue # 总是激活,无需处理
elif activation_type == "random": elif activation_type == ActionActivationType.RANDOM:
probability = action_info.get("random_activation_probability", ActionManager.DEFAULT_RANDOM_PROBABILITY) probability = action_info.random_activation_probability or ActionManager.DEFAULT_RANDOM_PROBABILITY
if not (random.random() < probability): if random.random() >= probability:
reason = f"RANDOM类型未触发概率{probability}" reason = f"RANDOM类型未触发概率{probability}"
deactivated_actions.append((action_name, reason)) deactivated_actions.append((action_name, reason))
logger.debug(f"{self.log_prefix}未激活动作: {action_name},原因: {reason}") logger.debug(f"{self.log_prefix}未激活动作: {action_name},原因: {reason}")
elif activation_type == "keyword": elif activation_type == ActionActivationType.KEYWORD:
if not self._check_keyword_activation(action_name, action_info, chat_content): if not self._check_keyword_activation(action_name, action_info, chat_content):
keywords = action_info.get("activation_keywords", []) keywords = action_info.activation_keywords
reason = f"关键词未匹配(关键词: {keywords}" reason = f"关键词未匹配(关键词: {keywords}"
deactivated_actions.append((action_name, reason)) deactivated_actions.append((action_name, reason))
logger.debug(f"{self.log_prefix}未激活动作: {action_name},原因: {reason}") logger.debug(f"{self.log_prefix}未激活动作: {action_name},原因: {reason}")
elif activation_type == "llm_judge": elif activation_type == ActionActivationType.LLM_JUDGE:
llm_judge_actions[action_name] = action_info llm_judge_actions[action_name] = action_info
else: else:

View File

@@ -14,7 +14,7 @@ from src.chat.utils.chat_message_builder import build_readable_messages, get_raw
from src.chat.utils.utils import get_chat_type_and_target_info from src.chat.utils.utils import get_chat_type_and_target_info
from src.chat.planner_actions.action_manager import ActionManager from src.chat.planner_actions.action_manager import ActionManager
from src.chat.message_receive.chat_stream import get_chat_manager from src.chat.message_receive.chat_stream import get_chat_manager
from src.plugin_system.base.component_types import ChatMode from src.plugin_system.base.component_types import ChatMode, ActionInfo
logger = get_logger("planner") logger = get_logger("planner")
@@ -26,7 +26,7 @@ def init_prompt():
Prompt( Prompt(
""" """
{time_block} {time_block}
{indentify_block} {identity_block}
你现在需要根据聊天内容选择的合适的action来参与聊天。 你现在需要根据聊天内容选择的合适的action来参与聊天。
{chat_context_description},以下是具体的聊天内容: {chat_context_description},以下是具体的聊天内容:
{chat_content_block} {chat_content_block}
@@ -78,6 +78,7 @@ class ActionPlanner:
action = "no_reply" # 默认动作 action = "no_reply" # 默认动作
reasoning = "规划器初始化默认" reasoning = "规划器初始化默认"
action_data = {} action_data = {}
current_available_actions: Dict[str, ActionInfo] = {}
try: try:
is_group_chat = True is_group_chat = True
@@ -89,7 +90,7 @@ class ActionPlanner:
# 获取完整的动作信息 # 获取完整的动作信息
all_registered_actions = self.action_manager.get_registered_actions() all_registered_actions = self.action_manager.get_registered_actions()
current_available_actions = {}
for action_name in current_available_actions_dict.keys(): for action_name in current_available_actions_dict.keys():
if action_name in all_registered_actions: if action_name in all_registered_actions:
current_available_actions[action_name] = all_registered_actions[action_name] current_available_actions[action_name] = all_registered_actions[action_name]
@@ -101,13 +102,17 @@ class ActionPlanner:
len(current_available_actions) == 1 and "no_reply" in current_available_actions len(current_available_actions) == 1 and "no_reply" in current_available_actions
): ):
action = "no_reply" action = "no_reply"
reasoning = "没有可用的动作" if not current_available_actions else "只有no_reply动作可用跳过规划" reasoning = "只有no_reply动作可用跳过规划" if current_available_actions else "没有可用的动作"
logger.info(f"{self.log_prefix}{reasoning}") logger.info(f"{self.log_prefix}{reasoning}")
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())}"
) )
return { return {
"action_result": {"action_type": action, "action_data": action_data, "reasoning": reasoning}, "action_result": {
"action_type": action,
"action_data": action_data,
"reasoning": reasoning,
},
} }
# --- 构建提示词 (调用修改后的 PromptBuilder 方法) --- # --- 构建提示词 (调用修改后的 PromptBuilder 方法) ---
@@ -135,7 +140,7 @@ class ActionPlanner:
except Exception as req_e: except Exception as req_e:
logger.error(f"{self.log_prefix}LLM 请求执行失败: {req_e}") logger.error(f"{self.log_prefix}LLM 请求执行失败: {req_e}")
reasoning = f"LLM 请求失败,你的模型出现问题: {req_e}" reasoning = f"LLM 请求失败,模型出现问题: {req_e}"
action = "no_reply" action = "no_reply"
if llm_content: if llm_content:
@@ -168,8 +173,8 @@ class ActionPlanner:
logger.warning( logger.warning(
f"{self.log_prefix}LLM 返回了当前不可用或无效的动作: '{action}' (可用: {list(current_available_actions.keys())}),将强制使用 'no_reply'" f"{self.log_prefix}LLM 返回了当前不可用或无效的动作: '{action}' (可用: {list(current_available_actions.keys())}),将强制使用 'no_reply'"
) )
action = "no_reply"
reasoning = f"LLM 返回了当前不可用的动作 '{action}' (可用: {list(current_available_actions.keys())})。原始理由: {reasoning}" reasoning = f"LLM 返回了当前不可用的动作 '{action}' (可用: {list(current_available_actions.keys())})。原始理由: {reasoning}"
action = "no_reply"
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}'")
@@ -185,8 +190,7 @@ class ActionPlanner:
is_parallel = False is_parallel = False
if action in current_available_actions: if action in current_available_actions:
action_info = current_available_actions[action] is_parallel = current_available_actions[action].parallel_action
is_parallel = action_info.get("parallel_action", False)
action_result = { action_result = {
"action_type": action, "action_type": action,
@@ -196,19 +200,17 @@ class ActionPlanner:
"is_parallel": is_parallel, "is_parallel": is_parallel,
} }
plan_result = { return {
"action_result": action_result, "action_result": action_result,
"action_prompt": prompt, "action_prompt": prompt,
} }
return plan_result
async def build_planner_prompt( async def build_planner_prompt(
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, current_available_actions: Dict[str, ActionInfo],
) -> str: ) -> str: # sourcery skip: use-join
"""构建 Planner LLM 的提示词 (获取模板并填充数据)""" """构建 Planner LLM 的提示词 (获取模板并填充数据)"""
try: try:
message_list_before_now = get_raw_msg_before_timestamp_with_chat( message_list_before_now = get_raw_msg_before_timestamp_with_chat(
@@ -247,23 +249,23 @@ class ActionPlanner:
action_options_block = "" action_options_block = ""
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["parameters"]: if using_actions_info.action_parameters:
param_text = "\n" param_text = "\n"
for param_name, param_description in using_actions_info["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["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,
) )
@@ -280,7 +282,7 @@ class ActionPlanner:
else: else:
bot_nickname = "" bot_nickname = ""
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}" identity_block = f"你的名字是{bot_name}{bot_nickname},你{bot_core_personality}"
planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt") planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt")
prompt = planner_prompt_template.format( prompt = planner_prompt_template.format(
@@ -291,7 +293,7 @@ class ActionPlanner:
no_action_block=no_action_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, identity_block=identity_block,
) )
return prompt return prompt

View File

@@ -1,33 +1,31 @@
import traceback import traceback
from typing import List, Optional, Dict, Any, Tuple
from src.chat.message_receive.message import MessageRecv, MessageThinking, MessageSending
from src.chat.message_receive.message import Seg # Local import needed after move
from src.chat.message_receive.message import UserInfo
from src.chat.message_receive.chat_stream import get_chat_manager
from src.common.logger import get_logger
from src.llm_models.utils_model import LLMRequest
from src.config.config import global_config
from src.chat.utils.timer_calculator import Timer # <--- Import Timer
from src.chat.message_receive.uni_message_sender import HeartFCSender
from src.chat.utils.utils import get_chat_type_and_target_info
from src.chat.message_receive.chat_stream import ChatStream
from src.chat.focus_chat.hfc_utils import parse_thinking_id_to_timestamp
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat
import time import time
import asyncio import asyncio
from src.chat.express.expression_selector import expression_selector
from src.mood.mood_manager import mood_manager
from src.person_info.relationship_fetcher import relationship_fetcher_manager
import random import random
import ast import ast
from src.person_info.person_info import get_person_info_manager
from datetime import datetime
import re import re
from typing import List, Optional, Dict, Any, Tuple
from datetime import datetime
from src.common.logger import get_logger
from src.config.config import global_config
from src.llm_models.utils_model import LLMRequest
from src.chat.message_receive.message import UserInfo, Seg, MessageRecv, MessageThinking, MessageSending
from src.chat.message_receive.chat_stream import get_chat_manager, ChatStream
from src.chat.message_receive.uni_message_sender import HeartFCSender
from src.chat.utils.timer_calculator import Timer # <--- Import Timer
from src.chat.utils.utils import get_chat_type_and_target_info
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat
from src.chat.focus_chat.hfc_utils import parse_thinking_id_to_timestamp
from src.chat.express.expression_selector import expression_selector
from src.chat.knowledge.knowledge_lib import qa_manager from src.chat.knowledge.knowledge_lib import qa_manager
from src.chat.memory_system.memory_activator import MemoryActivator from src.chat.memory_system.memory_activator import MemoryActivator
from src.mood.mood_manager import mood_manager
from src.person_info.relationship_fetcher import relationship_fetcher_manager
from src.person_info.person_info import get_person_info_manager
from src.tools.tool_executor import ToolExecutor from src.tools.tool_executor import ToolExecutor
from src.plugin_system.base.component_types import ActionInfo
logger = get_logger("replyer") logger = get_logger("replyer")
@@ -143,12 +141,12 @@ class DefaultReplyer:
return None return None
chat = anchor_message.chat_stream chat = anchor_message.chat_stream
messageinfo = anchor_message.message_info message_info = anchor_message.message_info
thinking_time_point = parse_thinking_id_to_timestamp(thinking_id) thinking_time_point = parse_thinking_id_to_timestamp(thinking_id)
bot_user_info = UserInfo( bot_user_info = UserInfo(
user_id=global_config.bot.qq_account, user_id=global_config.bot.qq_account,
user_nickname=global_config.bot.nickname, user_nickname=global_config.bot.nickname,
platform=messageinfo.platform, platform=message_info.platform,
) )
thinking_message = MessageThinking( thinking_message = MessageThinking(
@@ -168,7 +166,7 @@ class DefaultReplyer:
reply_data: Dict[str, Any] = None, reply_data: Dict[str, Any] = None,
reply_to: str = "", reply_to: str = "",
extra_info: str = "", extra_info: str = "",
available_actions: List[str] = None, available_actions: Optional[Dict[str, ActionInfo]] = None,
enable_tool: bool = True, enable_tool: bool = True,
enable_timeout: bool = False, enable_timeout: bool = False,
) -> Tuple[bool, Optional[str]]: ) -> Tuple[bool, Optional[str]]:
@@ -177,7 +175,7 @@ class DefaultReplyer:
(已整合原 HeartFCGenerator 的功能) (已整合原 HeartFCGenerator 的功能)
""" """
if available_actions is None: if available_actions is None:
available_actions = [] available_actions = {}
if reply_data is None: if reply_data is None:
reply_data = {} reply_data = {}
try: try:
@@ -323,8 +321,8 @@ class DefaultReplyer:
if not global_config.expression.enable_expression: if not global_config.expression.enable_expression:
return "" return ""
style_habbits = [] style_habits = []
grammar_habbits = [] grammar_habits = []
# 使用从处理器传来的选中表达方式 # 使用从处理器传来的选中表达方式
# LLM模式调用LLM选择5-10个然后随机选5个 # LLM模式调用LLM选择5-10个然后随机选5个
@@ -338,22 +336,22 @@ class DefaultReplyer:
if isinstance(expr, dict) and "situation" in expr and "style" in expr: if isinstance(expr, dict) and "situation" in expr and "style" in expr:
expr_type = expr.get("type", "style") expr_type = expr.get("type", "style")
if expr_type == "grammar": if expr_type == "grammar":
grammar_habbits.append(f"{expr['situation']}时,使用 {expr['style']}") grammar_habits.append(f"{expr['situation']}时,使用 {expr['style']}")
else: else:
style_habbits.append(f"{expr['situation']}时,使用 {expr['style']}") style_habits.append(f"{expr['situation']}时,使用 {expr['style']}")
else: else:
logger.debug(f"{self.log_prefix} 没有从处理器获得表达方式,将使用空的表达方式") logger.debug(f"{self.log_prefix} 没有从处理器获得表达方式,将使用空的表达方式")
# 不再在replyer中进行随机选择全部交给处理器处理 # 不再在replyer中进行随机选择全部交给处理器处理
style_habbits_str = "\n".join(style_habbits) style_habits_str = "\n".join(style_habits)
grammar_habbits_str = "\n".join(grammar_habbits) grammar_habits_str = "\n".join(grammar_habits)
# 动态构建expression habits块 # 动态构建expression habits块
expression_habits_block = "" expression_habits_block = ""
if style_habbits_str.strip(): if style_habits_str.strip():
expression_habits_block += f"你可以参考以下的语言习惯,如果情景合适就使用,不要盲目使用,不要生硬使用,而是结合到表达中:\n{style_habbits_str}\n\n" expression_habits_block += f"你可以参考以下的语言习惯,如果情景合适就使用,不要盲目使用,不要生硬使用,而是结合到表达中:\n{style_habits_str}\n\n"
if grammar_habbits_str.strip(): if grammar_habits_str.strip():
expression_habits_block += f"请你根据情景使用以下句法:\n{grammar_habbits_str}\n" expression_habits_block += f"请你根据情景使用以下句法:\n{grammar_habits_str}\n"
return expression_habits_block return expression_habits_block
@@ -361,13 +359,13 @@ class DefaultReplyer:
if not global_config.memory.enable_memory: if not global_config.memory.enable_memory:
return "" return ""
running_memorys = await self.memory_activator.activate_memory_with_chat_history( running_memories = await self.memory_activator.activate_memory_with_chat_history(
target_message=target, chat_history_prompt=chat_history target_message=target, chat_history_prompt=chat_history
) )
if running_memorys: if running_memories:
memory_str = "以下是当前在聊天中,你回忆起的记忆:\n" memory_str = "以下是当前在聊天中,你回忆起的记忆:\n"
for running_memory in running_memorys: for running_memory in running_memories:
memory_str += f"- {running_memory['content']}\n" memory_str += f"- {running_memory['content']}\n"
memory_block = memory_str memory_block = memory_str
else: else:
@@ -465,10 +463,10 @@ class DefaultReplyer:
return keywords_reaction_prompt return keywords_reaction_prompt
async def _time_and_run_task(self, coro, name: str): async def _time_and_run_task(self, coroutine, name: str):
"""一个简单的帮助函数,用于计时和运行异步任务,返回任务名、结果和耗时""" """一个简单的帮助函数,用于计时和运行异步任务,返回任务名、结果和耗时"""
start_time = time.time() start_time = time.time()
result = await coro result = await coroutine
end_time = time.time() end_time = time.time()
duration = end_time - start_time duration = end_time - start_time
return name, result, duration return name, result, duration
@@ -476,7 +474,7 @@ class DefaultReplyer:
async def build_prompt_reply_context( async def build_prompt_reply_context(
self, self,
reply_data=None, reply_data=None,
available_actions: List[str] = None, available_actions: Optional[Dict[str, ActionInfo]] = None,
enable_timeout: bool = False, enable_timeout: bool = False,
enable_tool: bool = True, enable_tool: bool = True,
) -> str: ) -> str:
@@ -495,7 +493,7 @@ class DefaultReplyer:
str: 构建好的上下文 str: 构建好的上下文
""" """
if available_actions is None: if available_actions is None:
available_actions = [] available_actions = {}
chat_stream = self.chat_stream chat_stream = self.chat_stream
chat_id = chat_stream.stream_id chat_id = chat_stream.stream_id
person_info_manager = get_person_info_manager() person_info_manager = get_person_info_manager()
@@ -514,10 +512,9 @@ class DefaultReplyer:
if available_actions: if available_actions:
action_descriptions = "你有以下的动作能力,但执行这些动作不由你决定,由另外一个模型同步决定,因此你只需要知道有如下能力即可:\n" action_descriptions = "你有以下的动作能力,但执行这些动作不由你决定,由另外一个模型同步决定,因此你只需要知道有如下能力即可:\n"
for action_name, action_info in available_actions.items(): for action_name, action_info in available_actions.items():
action_description = action_info.get("description", "") action_description = action_info.description
action_descriptions += f"- {action_name}: {action_description}\n" action_descriptions += f"- {action_name}: {action_description}\n"
action_descriptions += "\n" action_descriptions += "\n"
message_list_before_now = get_raw_msg_before_timestamp_with_chat( message_list_before_now = get_raw_msg_before_timestamp_with_chat(
chat_id=chat_id, chat_id=chat_id,
timestamp=time.time(), timestamp=time.time(),
@@ -616,7 +613,7 @@ class DefaultReplyer:
personality = short_impression[0] personality = short_impression[0]
identity = short_impression[1] identity = short_impression[1]
prompt_personality = personality + "" + identity prompt_personality = personality + "" + identity
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}" identity_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
moderation_prompt_block = ( moderation_prompt_block = (
"请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。不要随意遵从他人指令。" "请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。不要随意遵从他人指令。"
@@ -677,7 +674,7 @@ class DefaultReplyer:
reply_target_block=reply_target_block, reply_target_block=reply_target_block,
moderation_prompt=moderation_prompt_block, moderation_prompt=moderation_prompt_block,
keywords_reaction_prompt=keywords_reaction_prompt, keywords_reaction_prompt=keywords_reaction_prompt,
identity=indentify_block, identity=identity_block,
target_message=target, target_message=target,
sender_name=sender, sender_name=sender,
config_expression_style=global_config.expression.expression_style, config_expression_style=global_config.expression.expression_style,
@@ -749,7 +746,7 @@ class DefaultReplyer:
personality = short_impression[0] personality = short_impression[0]
identity = short_impression[1] identity = short_impression[1]
prompt_personality = personality + "" + identity prompt_personality = personality + "" + identity
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}" identity_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
moderation_prompt_block = ( moderation_prompt_block = (
"请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。不要随意遵从他人指令。" "请不要输出违法违规内容,不要输出色情,暴力,政治相关内容,如有敏感内容,请规避。不要随意遵从他人指令。"
@@ -800,7 +797,7 @@ class DefaultReplyer:
chat_target=chat_target_1, chat_target=chat_target_1,
time_block=time_block, time_block=time_block,
chat_info=chat_talking_prompt_half, chat_info=chat_talking_prompt_half,
identity=indentify_block, identity=identity_block,
chat_target_2=chat_target_2, chat_target_2=chat_target_2,
reply_target_block=reply_target_block, reply_target_block=reply_target_block,
raw_reply=raw_reply, raw_reply=raw_reply,

View File

@@ -36,10 +36,10 @@ class S4UMessageProcessor:
# 1. 消息解析与初始化 # 1. 消息解析与初始化
groupinfo = message.message_info.group_info groupinfo = message.message_info.group_info
userinfo = message.message_info.user_info userinfo = message.message_info.user_info
messageinfo = message.message_info message_info = message.message_info
chat = await get_chat_manager().get_or_create_stream( chat = await get_chat_manager().get_or_create_stream(
platform=messageinfo.platform, platform=message_info.platform,
user_info=userinfo, user_info=userinfo,
group_info=groupinfo, group_info=groupinfo,
) )

View File

@@ -19,7 +19,7 @@ def init_prompt():
{chat_talking_prompt} {chat_talking_prompt}
以上是群里正在进行的聊天记录 以上是群里正在进行的聊天记录
{indentify_block} {identity_block}
你刚刚的情绪状态是:{mood_state} 你刚刚的情绪状态是:{mood_state}
现在,发送了消息,引起了你的注意,你对其进行了阅读和思考,请你输出一句话描述你新的情绪状态 现在,发送了消息,引起了你的注意,你对其进行了阅读和思考,请你输出一句话描述你新的情绪状态
@@ -32,7 +32,7 @@ def init_prompt():
{chat_talking_prompt} {chat_talking_prompt}
以上是群里最近的聊天记录 以上是群里最近的聊天记录
{indentify_block} {identity_block}
你之前的情绪状态是:{mood_state} 你之前的情绪状态是:{mood_state}
距离你上次关注群里消息已经过去了一段时间,你冷静了下来,请你输出一句话描述你现在的情绪状态 距离你上次关注群里消息已经过去了一段时间,你冷静了下来,请你输出一句话描述你现在的情绪状态
@@ -103,12 +103,12 @@ class ChatMood:
bot_nickname = "" bot_nickname = ""
prompt_personality = global_config.personality.personality_core prompt_personality = global_config.personality.personality_core
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}" identity_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
prompt = await global_prompt_manager.format_prompt( prompt = await global_prompt_manager.format_prompt(
"change_mood_prompt", "change_mood_prompt",
chat_talking_prompt=chat_talking_prompt, chat_talking_prompt=chat_talking_prompt,
indentify_block=indentify_block, identity_block=identity_block,
mood_state=self.mood_state, mood_state=self.mood_state,
) )
@@ -147,12 +147,12 @@ class ChatMood:
bot_nickname = "" bot_nickname = ""
prompt_personality = global_config.personality.personality_core prompt_personality = global_config.personality.personality_core
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}" identity_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
prompt = await global_prompt_manager.format_prompt( prompt = await global_prompt_manager.format_prompt(
"regress_mood_prompt", "regress_mood_prompt",
chat_talking_prompt=chat_talking_prompt, chat_talking_prompt=chat_talking_prompt,
indentify_block=indentify_block, identity_block=identity_block,
mood_state=self.mood_state, mood_state=self.mood_state,
) )

View File

@@ -15,6 +15,7 @@ from src.chat.replyer.default_generator import DefaultReplyer
from src.chat.message_receive.chat_stream import ChatStream from src.chat.message_receive.chat_stream import ChatStream
from src.chat.utils.utils import process_llm_response from src.chat.utils.utils import process_llm_response
from src.chat.replyer.replyer_manager import replyer_manager from src.chat.replyer.replyer_manager import replyer_manager
from src.plugin_system.base.component_types import ActionInfo
logger = get_logger("generator_api") logger = get_logger("generator_api")
@@ -69,7 +70,7 @@ async def generate_reply(
action_data: Dict[str, Any] = None, action_data: Dict[str, Any] = None,
reply_to: str = "", reply_to: str = "",
extra_info: str = "", extra_info: str = "",
available_actions: List[str] = None, available_actions: Optional[Dict[str, ActionInfo]] = None,
enable_tool: bool = False, enable_tool: bool = False,
enable_splitter: bool = True, enable_splitter: bool = True,
enable_chinese_typo: bool = True, enable_chinese_typo: bool = True,

View File

@@ -66,7 +66,7 @@ class ComponentInfo:
name: str # 组件名称 name: str # 组件名称
component_type: ComponentType # 组件类型 component_type: ComponentType # 组件类型
description: str # 组件描述 description: str = "" # 组件描述
enabled: bool = True # 是否启用 enabled: bool = True # 是否启用
plugin_name: str = "" # 所属插件名称 plugin_name: str = "" # 所属插件名称
is_built_in: bool = False # 是否为内置组件 is_built_in: bool = False # 是否为内置组件
@@ -81,17 +81,19 @@ class ComponentInfo:
class ActionInfo(ComponentInfo): class ActionInfo(ComponentInfo):
"""动作组件信息""" """动作组件信息"""
action_parameters: Dict[str, str] = field(default_factory=dict) # 动作参数与描述,例如 {"param1": "描述1", "param2": "描述2"}
action_require: List[str] = field(default_factory=list) # 动作需求说明
associated_types: List[str] = field(default_factory=list) # 关联的消息类型
# 激活类型相关
focus_activation_type: ActionActivationType = ActionActivationType.ALWAYS focus_activation_type: ActionActivationType = ActionActivationType.ALWAYS
normal_activation_type: ActionActivationType = ActionActivationType.ALWAYS normal_activation_type: ActionActivationType = ActionActivationType.ALWAYS
random_activation_probability: float = 0.0 random_activation_probability: float = 0.0
llm_judge_prompt: str = "" llm_judge_prompt: str = ""
activation_keywords: List[str] = field(default_factory=list) # 激活关键词列表 activation_keywords: List[str] = field(default_factory=list) # 激活关键词列表
keyword_case_sensitive: bool = False keyword_case_sensitive: bool = False
# 模式和并行设置
mode_enable: ChatMode = ChatMode.ALL mode_enable: ChatMode = ChatMode.ALL
parallel_action: bool = False parallel_action: bool = False
action_parameters: Dict[str, Any] = field(default_factory=dict) # 动作参数
action_require: List[str] = field(default_factory=list) # 动作需求说明
associated_types: List[str] = field(default_factory=list) # 关联的消息类型
def __post_init__(self): def __post_init__(self):
super().__post_init__() super().__post_init__()

View File

@@ -35,7 +35,7 @@ class ComponentRegistry:
# Action特定注册表 # Action特定注册表
self._action_registry: Dict[str, BaseAction] = {} # action名 -> action类 self._action_registry: Dict[str, BaseAction] = {} # action名 -> action类
self._default_actions: Dict[str, str] = {} # 启用的action名 -> 描述 # self._action_descriptions: Dict[str, str] = {} # 启用的action名 -> 描述
# Command特定注册表 # Command特定注册表
self._command_registry: Dict[str, BaseCommand] = {} # command名 -> command类 self._command_registry: Dict[str, BaseCommand] = {} # command名 -> command类
@@ -99,13 +99,16 @@ class ComponentRegistry:
return True return True
def _register_action_component(self, action_info: ActionInfo, action_class: BaseAction): def _register_action_component(self, action_info: ActionInfo, action_class: BaseAction):
# -------------------------------- NEED REFACTORING --------------------------------
# -------------------------------- LOGIC ERROR -------------------------------------
"""注册Action组件到Action特定注册表""" """注册Action组件到Action特定注册表"""
action_name = action_info.name action_name = action_info.name
self._action_registry[action_name] = action_class self._action_registry[action_name] = action_class
# 如果启用,添加到默认动作集 # 如果启用,添加到默认动作集
if action_info.enabled: # ---- HERE ----
self._default_actions[action_name] = action_info.description # if action_info.enabled:
# self._action_descriptions[action_name] = action_info.description
def _register_command_component(self, command_info: CommandInfo, command_class: BaseCommand): def _register_command_component(self, command_info: CommandInfo, command_class: BaseCommand):
"""注册Command组件到Command特定注册表""" """注册Command组件到Command特定注册表"""
@@ -231,10 +234,6 @@ class ComponentRegistry:
"""获取Action注册表用于兼容现有系统""" """获取Action注册表用于兼容现有系统"""
return self._action_registry.copy() return self._action_registry.copy()
def get_default_actions(self) -> Dict[str, str]:
"""获取默认启用的Action列表用于兼容现有系统"""
return self._default_actions.copy()
def get_action_info(self, action_name: str) -> Optional[ActionInfo]: def get_action_info(self, action_name: str) -> Optional[ActionInfo]:
"""获取Action信息""" """获取Action信息"""
info = self.get_component_info(action_name, ComponentType.ACTION) info = self.get_component_info(action_name, ComponentType.ACTION)
@@ -343,6 +342,8 @@ class ComponentRegistry:
# === 状态管理方法 === # === 状态管理方法 ===
def enable_component(self, component_name: str, component_type: ComponentType = None) -> bool: def enable_component(self, component_name: str, component_type: ComponentType = None) -> bool:
# -------------------------------- NEED REFACTORING --------------------------------
# -------------------------------- LOGIC ERROR -------------------------------------
"""启用组件,支持命名空间解析""" """启用组件,支持命名空间解析"""
# 首先尝试找到正确的命名空间化名称 # 首先尝试找到正确的命名空间化名称
component_info = self.get_component_info(component_name, component_type) component_info = self.get_component_info(component_name, component_type)
@@ -364,13 +365,16 @@ class ComponentRegistry:
if namespaced_name in self._components: if namespaced_name in self._components:
self._components[namespaced_name].enabled = True self._components[namespaced_name].enabled = True
# 如果是Action更新默认动作集 # 如果是Action更新默认动作集
if isinstance(component_info, ActionInfo): # ---- HERE ----
self._default_actions[component_name] = component_info.description # if isinstance(component_info, ActionInfo):
# self._action_descriptions[component_name] = component_info.description
logger.debug(f"已启用组件: {component_name} -> {namespaced_name}") logger.debug(f"已启用组件: {component_name} -> {namespaced_name}")
return True return True
return False return False
def disable_component(self, component_name: str, component_type: ComponentType = None) -> bool: def disable_component(self, component_name: str, component_type: ComponentType = None) -> bool:
# -------------------------------- NEED REFACTORING --------------------------------
# -------------------------------- LOGIC ERROR -------------------------------------
"""禁用组件,支持命名空间解析""" """禁用组件,支持命名空间解析"""
# 首先尝试找到正确的命名空间化名称 # 首先尝试找到正确的命名空间化名称
component_info = self.get_component_info(component_name, component_type) component_info = self.get_component_info(component_name, component_type)
@@ -392,8 +396,9 @@ class ComponentRegistry:
if namespaced_name in self._components: if namespaced_name in self._components:
self._components[namespaced_name].enabled = False self._components[namespaced_name].enabled = False
# 如果是Action从默认动作集中移除 # 如果是Action从默认动作集中移除
if component_name in self._default_actions: # ---- HERE ----
del self._default_actions[component_name] # if component_name in self._action_descriptions:
# del self._action_descriptions[component_name]
logger.debug(f"已禁用组件: {component_name} -> {namespaced_name}") logger.debug(f"已禁用组件: {component_name} -> {namespaced_name}")
return True return True
return False return False

View File

@@ -37,16 +37,14 @@ class DependencyManager:
missing_optional = [] missing_optional = []
for dep in dependencies: for dep in dependencies:
if not self._is_package_available(dep.package_name): if self._is_package_available(dep.package_name):
if dep.optional:
missing_optional.append(dep)
logger.warning(f"可选依赖包缺失: {dep.package_name} - {dep.description}")
else:
missing_required.append(dep)
logger.error(f"必需依赖包缺失: {dep.package_name} - {dep.description}")
else:
logger.debug(f"依赖包已存在: {dep.package_name}") logger.debug(f"依赖包已存在: {dep.package_name}")
elif dep.optional:
missing_optional.append(dep)
logger.warning(f"可选依赖包缺失: {dep.package_name} - {dep.description}")
else:
missing_required.append(dep)
logger.error(f"必需依赖包缺失: {dep.package_name} - {dep.description}")
return missing_required, missing_optional return missing_required, missing_optional
def _is_package_available(self, package_name: str) -> bool: def _is_package_available(self, package_name: str) -> bool:

View File

@@ -24,12 +24,14 @@ class PluginManager:
""" """
def __init__(self): def __init__(self):
self.plugin_directories: List[str] = [] self.plugin_directories: List[str] = [] # 插件根目录列表
self.loaded_plugins: Dict[str, "BasePlugin"] = {} self.plugin_classes: Dict[str, Type[BasePlugin]] = {} # 全局插件类注册表,插件名 -> 插件类
self.failed_plugins: Dict[str, str] = {} self.plugin_paths: Dict[str, str] = {} # 记录插件名到目录路径的映射,插件名 -> 目录路径
self.plugin_paths: Dict[str, str] = {} # 记录插件名到目录路径的映射
self.loaded_plugins: Dict[str, BasePlugin] = {} # 已加载的插件类实例注册表,插件名 -> 插件类实例
self.failed_plugins: Dict[str, str] = {} # 记录加载失败的插件类及其错误信息,插件名 -> 错误信息
self.events_subscriptions: Dict[EventType, List[Callable]] = {} self.events_subscriptions: Dict[EventType, List[Callable]] = {}
self.plugin_classes: Dict[str, Type[BasePlugin]] = {} # 全局插件类注册表
# 确保插件目录存在 # 确保插件目录存在
self._ensure_plugin_directories() self._ensure_plugin_directories()