feat:处理器处理时间上限,处理并行模式,planner和思考prompt,循环观察器大优化
feat:增加了处理器处理时间上限,记忆处理并行模式,优化了planner和思考prompt,优化了循环观察器
This commit is contained in:
@@ -19,11 +19,13 @@ def init_prompt() -> None:
|
||||
learn_style_prompt = """
|
||||
{chat_str}
|
||||
|
||||
请从上面这段群聊中概括除了人名为"SELF"之外的人的语言风格,只考虑文字,不要考虑表情包和图片
|
||||
不要涉及具体的人名,只考虑语言风格
|
||||
语言风格包含特殊内容和情感
|
||||
思考有没有特殊的梗,一并总结成语言风格
|
||||
总结成如下格式的规律,总结的内容要详细,但具有概括性:
|
||||
请从上面这段群聊中概括除了人名为"SELF"之外的人的语言风格
|
||||
1. 只考虑文字,不要考虑表情包和图片
|
||||
2. 不要涉及具体的人名,只考虑语言风格
|
||||
3. 语言风格包含特殊内容和情感
|
||||
4. 思考有没有特殊的梗,一并总结成语言风格
|
||||
5. 例子仅供参考,请严格根据群聊内容总结!!!
|
||||
注意:总结成如下格式的规律,总结的内容要详细,但具有概括性:
|
||||
当"xxx"时,可以"xxx", xxx不超过10个字
|
||||
|
||||
例如:
|
||||
@@ -31,7 +33,7 @@ def init_prompt() -> None:
|
||||
当"表示讽刺的赞同,不想讲道理"时,使用"对对对"
|
||||
当"想说明某个观点,但懒得明说",使用"懂的都懂"
|
||||
|
||||
注意不要总结你自己的发言
|
||||
注意不要总结你自己(SELF)的发言
|
||||
现在请你概括
|
||||
"""
|
||||
Prompt(learn_style_prompt, "learn_style_prompt")
|
||||
@@ -40,9 +42,10 @@ def init_prompt() -> None:
|
||||
{chat_str}
|
||||
|
||||
请从上面这段群聊中概括除了人名为"SELF"之外的人的语法和句法特点,只考虑纯文字,不要考虑表情包和图片
|
||||
不要总结【图片】,【动画表情】,[图片],[动画表情],不总结 表情符号 at @ 回复 和[回复]
|
||||
不要涉及具体的人名,只考虑语法和句法特点,
|
||||
语法和句法特点要包括,句子长短(具体字数),有何种语病,如何拆分句子。
|
||||
1.不要总结【图片】,【动画表情】,[图片],[动画表情],不总结 表情符号 at @ 回复 和[回复]
|
||||
2.不要涉及具体的人名,只考虑语法和句法特点,
|
||||
3.语法和句法特点要包括,句子长短(具体字数),有何种语病,如何拆分句子。
|
||||
4. 例子仅供参考,请严格根据群聊内容总结!!!
|
||||
总结成如下格式的规律,总结的内容要简洁,不浮夸:
|
||||
当"xxx"时,可以"xxx"
|
||||
|
||||
@@ -51,7 +54,7 @@ def init_prompt() -> None:
|
||||
当"不用详细说明的一般表达"时,使用"非常简洁的句子"的句法
|
||||
当"需要单纯简单的确认"时,使用"单字或几个字的肯定(1-2个字)"的句法
|
||||
|
||||
注意不要总结你自己的发言
|
||||
注意不要总结你自己(SELF)的发言
|
||||
现在请你概括
|
||||
"""
|
||||
Prompt(learn_grammar_prompt, "learn_grammar_prompt")
|
||||
|
||||
@@ -44,21 +44,10 @@ PROCESSOR_CLASSES = {
|
||||
"ToolProcessor": (ToolProcessor, "tool_use_processor"),
|
||||
"WorkingMemoryProcessor": (WorkingMemoryProcessor, "working_memory_processor"),
|
||||
"SelfProcessor": (SelfProcessor, "self_identify_processor"),
|
||||
# "ActionProcessor": (ActionProcessor, "action_processor"), # 这个处理器不需要配置键名,默认启用
|
||||
}
|
||||
|
||||
|
||||
WAITING_TIME_THRESHOLD = 300 # 等待新消息时间阈值,单位秒
|
||||
|
||||
EMOJI_SEND_PRO = 0.3 # 设置一个概率,比如 30% 才真的发
|
||||
|
||||
CONSECUTIVE_NO_REPLY_THRESHOLD = 3 # 连续不回复的阈值
|
||||
|
||||
logger = get_logger("hfc") # Logger Name Changed
|
||||
|
||||
# 设定处理器超时时间(秒)
|
||||
PROCESSOR_TIMEOUT = 30
|
||||
|
||||
|
||||
async def _handle_cycle_delay(action_taken_this_cycle: bool, cycle_start_time: float, log_prefix: str):
|
||||
"""处理循环延迟"""
|
||||
@@ -150,7 +139,7 @@ class HeartFChatting:
|
||||
# 添加循环信息管理相关的属性
|
||||
self._cycle_counter = 0
|
||||
self._cycle_history: Deque[CycleDetail] = deque(maxlen=10) # 保留最近10个循环的信息
|
||||
self._current_cycle: Optional[CycleDetail] = None
|
||||
self._current_cycle_detail: Optional[CycleDetail] = None
|
||||
self._shutting_down: bool = False # 关闭标志位
|
||||
|
||||
# 存储回调函数
|
||||
@@ -262,12 +251,12 @@ class HeartFChatting:
|
||||
try:
|
||||
exception = task.exception()
|
||||
if exception:
|
||||
logger.error(f"{self.log_prefix} HeartFChatting: 麦麦脱离了聊天(异常): {exception}")
|
||||
logger.error(f"{self.log_prefix} HeartFChatting: 脱离了聊天(异常): {exception}")
|
||||
logger.error(traceback.format_exc()) # Log full traceback for exceptions
|
||||
else:
|
||||
logger.info(f"{self.log_prefix} HeartFChatting: 麦麦脱离了聊天 (外部停止)")
|
||||
logger.info(f"{self.log_prefix} HeartFChatting: 脱离了聊天 (外部停止)")
|
||||
except asyncio.CancelledError:
|
||||
logger.info(f"{self.log_prefix} HeartFChatting: 麦麦脱离了聊天(任务取消)")
|
||||
logger.info(f"{self.log_prefix} HeartFChatting: 脱离了聊天(任务取消)")
|
||||
finally:
|
||||
self._loop_active = False
|
||||
self._loop_task = None
|
||||
@@ -286,7 +275,8 @@ class HeartFChatting:
|
||||
|
||||
# 创建新的循环信息
|
||||
self._cycle_counter += 1
|
||||
self._current_cycle = CycleDetail(self._cycle_counter)
|
||||
self._current_cycle_detail = CycleDetail(self._cycle_counter)
|
||||
self._current_cycle_detail.prefix = self.log_prefix
|
||||
|
||||
# 初始化周期状态
|
||||
cycle_timers = {}
|
||||
@@ -295,13 +285,12 @@ class HeartFChatting:
|
||||
# 执行规划和处理阶段
|
||||
async with self._get_cycle_context():
|
||||
thinking_id = "tid" + str(round(time.time(), 2))
|
||||
self._current_cycle.set_thinking_id(thinking_id)
|
||||
self._current_cycle_detail.set_thinking_id(thinking_id)
|
||||
# 主循环:思考->决策->执行
|
||||
async with global_prompt_manager.async_message_scope(self.chat_stream.context.get_template_name()):
|
||||
logger.debug(f"模板 {self.chat_stream.context.get_template_name()}")
|
||||
loop_info = await self._observe_process_plan_action_loop(cycle_timers, thinking_id)
|
||||
|
||||
print(loop_info["loop_action_info"]["command"])
|
||||
if loop_info["loop_action_info"]["command"] == "stop_focus_chat":
|
||||
logger.info(f"{self.log_prefix} 麦麦决定停止专注聊天")
|
||||
# 如果设置了回调函数,则调用它
|
||||
@@ -314,10 +303,10 @@ class HeartFChatting:
|
||||
logger.error(traceback.format_exc())
|
||||
break
|
||||
|
||||
self._current_cycle.set_loop_info(loop_info)
|
||||
self._current_cycle_detail.set_loop_info(loop_info)
|
||||
|
||||
self.hfcloop_observation.add_loop_info(self._current_cycle)
|
||||
self._current_cycle.timers = cycle_timers
|
||||
self.hfcloop_observation.add_loop_info(self._current_cycle_detail)
|
||||
self._current_cycle_detail.timers = cycle_timers
|
||||
|
||||
# 防止循环过快消耗资源
|
||||
await _handle_cycle_delay(
|
||||
@@ -325,8 +314,8 @@ class HeartFChatting:
|
||||
)
|
||||
|
||||
# 完成当前循环并保存历史
|
||||
self._current_cycle.complete_cycle()
|
||||
self._cycle_history.append(self._current_cycle)
|
||||
self._current_cycle_detail.complete_cycle()
|
||||
self._cycle_history.append(self._current_cycle_detail)
|
||||
|
||||
# 记录循环信息和计时器结果
|
||||
timer_strings = []
|
||||
@@ -335,7 +324,7 @@ class HeartFChatting:
|
||||
timer_strings.append(f"{name}: {formatted_time}")
|
||||
|
||||
# 新增:输出每个处理器的耗时
|
||||
processor_time_costs = self._current_cycle.loop_processor_info.get("processor_time_costs", {})
|
||||
processor_time_costs = self._current_cycle_detail.loop_processor_info.get("processor_time_costs", {})
|
||||
processor_time_strings = []
|
||||
for pname, ptime in processor_time_costs.items():
|
||||
formatted_ptime = f"{ptime * 1000:.2f}毫秒" if ptime < 1 else f"{ptime:.2f}秒"
|
||||
@@ -345,9 +334,9 @@ class HeartFChatting:
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"{self.log_prefix} 第{self._current_cycle.cycle_id}次思考,"
|
||||
f"耗时: {self._current_cycle.end_time - self._current_cycle.start_time:.1f}秒, "
|
||||
f"动作: {self._current_cycle.loop_plan_info['action_result']['action_type']}"
|
||||
f"{self.log_prefix} 第{self._current_cycle_detail.cycle_id}次思考,"
|
||||
f"耗时: {self._current_cycle_detail.end_time - self._current_cycle_detail.start_time:.1f}秒, "
|
||||
f"动作: {self._current_cycle_detail.loop_plan_info['action_result']['action_type']}"
|
||||
+ (f"\n详情: {'; '.join(timer_strings)}" if timer_strings else "")
|
||||
+ processor_time_log
|
||||
)
|
||||
@@ -384,7 +373,7 @@ class HeartFChatting:
|
||||
self._processing_lock.release()
|
||||
|
||||
async def _process_processors(
|
||||
self, observations: List[Observation], running_memorys: List[Dict[str, Any]], cycle_timers: dict
|
||||
self, observations: List[Observation], running_memorys: List[Dict[str, Any]]
|
||||
) -> tuple[List[InfoBase], Dict[str, float]]:
|
||||
# 记录并行任务开始时间
|
||||
parallel_start_time = time.time()
|
||||
@@ -400,7 +389,7 @@ class HeartFChatting:
|
||||
async def run_with_timeout(proc=processor):
|
||||
return await asyncio.wait_for(
|
||||
proc.process_info(observations=observations, running_memorys=running_memorys),
|
||||
timeout=PROCESSOR_TIMEOUT,
|
||||
timeout=global_config.focus_chat.processor_max_time,
|
||||
)
|
||||
|
||||
task = asyncio.create_task(run_with_timeout())
|
||||
@@ -429,8 +418,8 @@ class HeartFChatting:
|
||||
# 记录耗时
|
||||
processor_time_costs[processor_name] = duration_since_parallel_start
|
||||
except asyncio.TimeoutError:
|
||||
logger.info(f"{self.log_prefix} 处理器 {processor_name} 超时(>{PROCESSOR_TIMEOUT}s),已跳过")
|
||||
processor_time_costs[processor_name] = PROCESSOR_TIMEOUT
|
||||
logger.info(f"{self.log_prefix} 处理器 {processor_name} 超时(>{global_config.focus_chat.processor_max_time}s),已跳过")
|
||||
processor_time_costs[processor_name] = global_config.focus_chat.processor_max_time
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"{self.log_prefix} 处理器 {processor_name} 执行失败,耗时 (自并行开始): {duration_since_parallel_start:.2f}秒. 错误: {e}",
|
||||
@@ -473,28 +462,42 @@ class HeartFChatting:
|
||||
}
|
||||
|
||||
self.all_observations = observations
|
||||
|
||||
with Timer("回忆", cycle_timers):
|
||||
running_memorys = await self.memory_activator.activate_memory(observations)
|
||||
|
||||
|
||||
with Timer("调整动作", cycle_timers):
|
||||
# 处理特殊的观察
|
||||
await self.action_modifier.modify_actions(observations=observations, running_memorys=running_memorys)
|
||||
await self.action_modifier.modify_actions(observations=observations)
|
||||
await self.action_observation.observe()
|
||||
observations.append(self.action_observation)
|
||||
|
||||
with Timer("执行 信息处理器", cycle_timers):
|
||||
all_plan_info, processor_time_costs = await self._process_processors(
|
||||
observations, running_memorys, cycle_timers
|
||||
)
|
||||
# 根据配置决定是否并行执行回忆和处理器阶段
|
||||
# print(global_config.focus_chat.parallel_processing)
|
||||
if global_config.focus_chat.parallel_processing:
|
||||
# 并行执行回忆和处理器阶段
|
||||
with Timer("并行回忆和处理", cycle_timers):
|
||||
memory_task = asyncio.create_task(self.memory_activator.activate_memory(observations))
|
||||
processor_task = asyncio.create_task(self._process_processors(observations, []))
|
||||
|
||||
# 等待两个任务完成
|
||||
running_memorys, (all_plan_info, processor_time_costs) = await asyncio.gather(memory_task, processor_task)
|
||||
else:
|
||||
# 串行执行
|
||||
with Timer("回忆", cycle_timers):
|
||||
running_memorys = await self.memory_activator.activate_memory(observations)
|
||||
|
||||
with Timer("执行 信息处理器", cycle_timers):
|
||||
all_plan_info, processor_time_costs = await self._process_processors(
|
||||
observations, running_memorys
|
||||
)
|
||||
|
||||
loop_processor_info = {
|
||||
"all_plan_info": all_plan_info,
|
||||
"processor_time_costs": processor_time_costs,
|
||||
}
|
||||
|
||||
|
||||
loop_processor_info = {
|
||||
"all_plan_info": all_plan_info,
|
||||
"processor_time_costs": processor_time_costs,
|
||||
}
|
||||
|
||||
with Timer("规划器", cycle_timers):
|
||||
plan_result = await self.action_planner.plan(all_plan_info, cycle_timers)
|
||||
plan_result = await self.action_planner.plan(all_plan_info, running_memorys)
|
||||
|
||||
loop_plan_info = {
|
||||
"action_result": plan_result.get("action_result", {}),
|
||||
@@ -526,6 +529,7 @@ class HeartFChatting:
|
||||
"action_taken": success,
|
||||
"reply_text": reply_text,
|
||||
"command": command,
|
||||
"taken_time": time.time(),
|
||||
}
|
||||
|
||||
loop_info = {
|
||||
|
||||
@@ -24,9 +24,7 @@ logger = get_logger("processor")
|
||||
def init_prompt():
|
||||
group_prompt = """
|
||||
你的名字是{bot_name}
|
||||
{memory_str}
|
||||
{extra_info}
|
||||
{relation_prompt}
|
||||
{memory_str}{extra_info}{relation_prompt}
|
||||
{cycle_info_block}
|
||||
现在是{time_now},你正在上网,和qq群里的网友们聊天,以下是正在进行的聊天内容:
|
||||
{chat_observe_info}
|
||||
@@ -46,15 +44,11 @@ def init_prompt():
|
||||
|
||||
private_prompt = """
|
||||
你的名字是{bot_name}
|
||||
{memory_str}
|
||||
{extra_info}
|
||||
{relation_prompt}
|
||||
{memory_str}{extra_info}{relation_prompt}
|
||||
{cycle_info_block}
|
||||
现在是{time_now},你正在上网,和qq群里的网友们聊天,以下是正在进行的聊天内容:
|
||||
{chat_observe_info}
|
||||
|
||||
{action_observe_info}
|
||||
|
||||
以下是你之前对聊天的观察和规划,你的名字是{bot_name}:
|
||||
{last_mind}
|
||||
|
||||
@@ -155,14 +149,14 @@ class MindProcessor(BaseProcessor):
|
||||
|
||||
# ---------- 0. 更新和清理 structured_info ----------
|
||||
if self.structured_info:
|
||||
updated_info = []
|
||||
for item in self.structured_info:
|
||||
item["ttl"] -= 1
|
||||
if item["ttl"] > 0:
|
||||
updated_info.append(item)
|
||||
else:
|
||||
logger.debug(f"{self.log_prefix} 移除过期的 structured_info 项: {item['id']}")
|
||||
self.structured_info = updated_info
|
||||
# updated_info = []
|
||||
# for item in self.structured_info:
|
||||
# item["ttl"] -= 1
|
||||
# if item["ttl"] > 0:
|
||||
# updated_info.append(item)
|
||||
# else:
|
||||
# logger.debug(f"{self.log_prefix} 移除过期的 structured_info 项: {item['id']}")
|
||||
# self.structured_info = updated_info
|
||||
self._update_structured_info_str()
|
||||
logger.debug(
|
||||
f"{self.log_prefix} 当前完整的 structured_info: {safe_json_dumps(self.structured_info, ensure_ascii=False)}"
|
||||
|
||||
@@ -25,9 +25,7 @@ def init_prompt():
|
||||
你是一个AI,但是你伪装成了一个人类,你的人格是,{prompt_personality}
|
||||
{indentify_block}
|
||||
|
||||
{relation_prompt}
|
||||
{memory_str}
|
||||
|
||||
{relation_prompt}{memory_str}
|
||||
现在是{time_now},你正在上网,和qq群里的网友们聊天,以下是正在进行的聊天内容:
|
||||
{chat_observe_info}
|
||||
|
||||
|
||||
@@ -23,10 +23,7 @@ def init_prompt():
|
||||
# 添加工具执行器提示词
|
||||
tool_executor_prompt = """
|
||||
你是一个专门执行工具的助手。你的名字是{bot_name}。现在是{time_now}。
|
||||
|
||||
你当前的额外信息:
|
||||
{memory_str}
|
||||
|
||||
群里正在进行的聊天内容:
|
||||
{chat_observe_info}
|
||||
|
||||
@@ -165,8 +162,9 @@ class ToolProcessor(BaseProcessor):
|
||||
logger.debug(f"开始执行工具调用{prompt}")
|
||||
response, _, tool_calls = await self.llm_model.generate_response_tool_async(prompt=prompt, tools=tools)
|
||||
|
||||
logger.debug(f"获取到工具原始输出:\n{tool_calls}")
|
||||
# 处理工具调用和结果收集,类似于SubMind中的逻辑
|
||||
if tool_calls:
|
||||
logger.debug(f"获取到工具原始输出:\n{tool_calls}")
|
||||
# 处理工具调用和结果收集,类似于SubMind中的逻辑
|
||||
new_structured_items = []
|
||||
used_tools = [] # 记录使用了哪些工具
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ class NoReplyAction(BaseAction):
|
||||
action_parameters = {}
|
||||
action_require = [
|
||||
"话题无关/无聊/不感兴趣/不懂",
|
||||
"最后一条消息是你自己发的且无人回应你",
|
||||
"你发送了太多消息,且无人回复",
|
||||
"聊天记录中最新一条消息是你自己发的且无人回应你",
|
||||
"你连续发送了太多消息,且无人回复",
|
||||
]
|
||||
default = True
|
||||
|
||||
|
||||
@@ -28,11 +28,8 @@ class ActionModifier:
|
||||
async def modify_actions(
|
||||
self,
|
||||
observations: Optional[List[Observation]] = None,
|
||||
running_memorys: Optional[List[Dict]] = None,
|
||||
**kwargs: Any,
|
||||
):
|
||||
# print(f"observations: {observations}")
|
||||
# processed_infos = []
|
||||
|
||||
# 处理Observation对象
|
||||
if observations:
|
||||
|
||||
@@ -26,9 +26,8 @@ def init_prompt():
|
||||
"""
|
||||
你的自我认知是:
|
||||
{self_info_block}
|
||||
|
||||
{extra_info_block}
|
||||
|
||||
{memory_str}
|
||||
你需要基于以下信息决定如何参与对话
|
||||
这些信息可能会有冲突,请你整合这些信息,并选择一个最合适的action:
|
||||
{chat_content_block}
|
||||
@@ -49,7 +48,7 @@ def init_prompt():
|
||||
请你以下面格式输出你选择的action:
|
||||
{{
|
||||
"action": "action_name",
|
||||
"reasoning": "你的决策理由",
|
||||
"reasoning": "说明你做出该action的原因",
|
||||
"参数1": "参数1的值",
|
||||
"参数2": "参数2的值",
|
||||
"参数3": "参数3的值",
|
||||
@@ -84,13 +83,13 @@ class ActionPlanner:
|
||||
|
||||
self.action_manager = action_manager
|
||||
|
||||
async def plan(self, all_plan_info: List[InfoBase], cycle_timers: dict) -> Dict[str, Any]:
|
||||
async def plan(self, all_plan_info: List[InfoBase], running_memorys: List[Dict[str, Any]]) -> Dict[str, Any]:
|
||||
"""
|
||||
规划器 (Planner): 使用LLM根据上下文决定做出什么动作。
|
||||
|
||||
参数:
|
||||
all_plan_info: 所有计划信息
|
||||
cycle_timers: 计时器字典
|
||||
running_memorys: 回忆信息
|
||||
"""
|
||||
|
||||
action = "no_reply" # 默认动作
|
||||
@@ -169,6 +168,7 @@ class ActionPlanner:
|
||||
current_available_actions=current_available_actions, # <-- Pass determined actions
|
||||
cycle_info=cycle_info, # <-- Pass cycle info
|
||||
extra_info=extra_info,
|
||||
running_memorys=running_memorys,
|
||||
)
|
||||
|
||||
# --- 调用 LLM (普通文本生成) ---
|
||||
@@ -259,10 +259,22 @@ class ActionPlanner:
|
||||
current_available_actions: Dict[str, ActionInfo],
|
||||
cycle_info: Optional[str],
|
||||
extra_info: list[str],
|
||||
running_memorys: List[Dict[str, Any]],
|
||||
) -> str:
|
||||
"""构建 Planner LLM 的提示词 (获取模板并填充数据)"""
|
||||
try:
|
||||
# --- Determine chat context ---
|
||||
|
||||
memory_str = ""
|
||||
if global_config.focus_chat.parallel_processing:
|
||||
memory_str = ""
|
||||
if running_memorys:
|
||||
memory_str = "以下是当前在聊天中,你回忆起的记忆:\n"
|
||||
for running_memory in running_memorys:
|
||||
memory_str += f"{running_memory['topic']}: {running_memory['content']}\n"
|
||||
|
||||
|
||||
|
||||
|
||||
chat_context_description = "你现在正在一个群聊中"
|
||||
chat_target_name = None # Only relevant for private
|
||||
if not is_group_chat and chat_target_info:
|
||||
@@ -324,6 +336,7 @@ class ActionPlanner:
|
||||
planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt")
|
||||
prompt = planner_prompt_template.format(
|
||||
self_info_block=self_info_block,
|
||||
memory_str=memory_str,
|
||||
# bot_name=global_config.bot.nickname,
|
||||
prompt_personality=personality_block,
|
||||
chat_context_description=chat_context_description,
|
||||
|
||||
Reference in New Issue
Block a user