Add timeout handling and error recovery in focus chat processing

pull/1045/head
Cursor Agent 2025-06-17 01:22:54 +00:00
parent 6fce7f8dcd
commit 570a9418ab
2 changed files with 85 additions and 33 deletions

View File

@ -50,24 +50,24 @@ def init_prompt():
Prompt(
"""
你可以参考以下的语言习惯如果情景合适就使用不要盲目使用,不要生硬使用而是结合到表达中
{style_habbits}
你现在正在群里聊天以下是群里正在进行的聊天内容
你正在和{sender_name}进行私聊以下是聊天内容
{chat_info}
以上是聊天内容你需要了解聊天记录中的内容
你的名字是{bot_name}{prompt_personality}对于"{target_message}"你想表达{in_mind_reply}原因是{reason}
请以友好直接的方式回复你的回复应该
1. 简洁明了直接表达核心意思
2. 语气友好但不过分亲密
3. 保持适当的礼貌和距离感
4. 避免过于复杂的表达方式
5. 不要使用群聊中的梗或过于随意的表达
{config_expression_style}
不要输出多余内容(包括前后缀冒号和引号括号表情包等)只输出一条回复就好
{chat_target}
你的名字是{bot_name}{prompt_personality}在这聊天中"{target_message}"引起了你的注意对这句话你想表达{in_mind_reply},原因是{reason}你现在要思考怎么回复
你需要使用合适的语法和句法参考聊天内容组织一条日常且口语化的回复
请你根据情景使用以下句法
{grammar_habbits}
{config_expression_style}你可以完全重组回复保留最基本的表达含义就好但重组后保持语意通顺
不要浮夸不要夸张修辞平淡且不要输出多余内容(包括前后缀冒号和引号括号表情包at或 @等 )只输出一条回复就好
现在你说
""",
"default_expressor_private_prompt", # New template for private FOCUSED chat
"default_expressor_private_prompt",
)

View File

@ -490,24 +490,52 @@ class HeartFChatting:
observations.append(self.action_observation)
# 根据配置决定是否并行执行回忆和处理器阶段
# 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
)
try:
# 等待两个任务完成,设置超时
running_memorys, (all_plan_info, processor_time_costs) = await asyncio.wait_for(
asyncio.gather(memory_task, processor_task),
timeout=global_config.focus_chat.processor_max_time * 2 # 双倍处理器超时时间
)
except asyncio.TimeoutError:
logger.error(f"{self.log_prefix} 并行处理超时")
# 取消未完成的任务
for task in [memory_task, processor_task]:
if not task.done():
task.cancel()
# 返回空结果
return {
"loop_observation_info": loop_observation_info,
"loop_processor_info": {"all_plan_info": [], "processor_time_costs": {}},
"loop_plan_info": {"action_result": {"action_type": "no_reply", "action_data": {}, "reasoning": "处理超时"}},
"loop_action_info": {"action_taken": False, "command": "no_reply", "reason": "处理超时"},
}
else:
# 串行执行
with Timer("回忆", cycle_timers):
running_memorys = await self.memory_activator.activate_memory(observations)
try:
running_memorys = await asyncio.wait_for(
self.memory_activator.activate_memory(observations),
timeout=global_config.focus_chat.processor_max_time
)
except asyncio.TimeoutError:
logger.error(f"{self.log_prefix} 回忆处理超时")
running_memorys = []
with Timer("执行 信息处理器", cycle_timers):
all_plan_info, processor_time_costs = await self._process_processors(observations, running_memorys)
try:
all_plan_info, processor_time_costs = await asyncio.wait_for(
self._process_processors(observations, running_memorys),
timeout=global_config.focus_chat.processor_max_time
)
except asyncio.TimeoutError:
logger.error(f"{self.log_prefix} 信息处理器执行超时")
all_plan_info, processor_time_costs = [], {}
loop_processor_info = {
"all_plan_info": all_plan_info,
@ -515,24 +543,41 @@ class HeartFChatting:
}
with Timer("规划器", cycle_timers):
# 私聊时使用简单规划
if not is_group_chat:
plan_result = await self.action_planner.plan_simple(all_plan_info, running_memorys)
else:
plan_result = await self.action_planner.plan(all_plan_info, running_memorys)
try:
# 私聊时使用简单规划
if not is_group_chat:
plan_result = await asyncio.wait_for(
self.action_planner.plan_simple(all_plan_info, running_memorys),
timeout=global_config.focus_chat.processor_max_time
)
else:
plan_result = await asyncio.wait_for(
self.action_planner.plan(all_plan_info, running_memorys),
timeout=global_config.focus_chat.processor_max_time
)
except asyncio.TimeoutError:
logger.error(f"{self.log_prefix} 规划器执行超时")
plan_result = {"action_type": "no_reply", "action_data": {}, "reasoning": "规划超时"}
loop_plan_info = {
"action_result": plan_result,
}
with Timer("执行动作", cycle_timers):
action_taken, action_command, action_reason = await self._handle_action(
action=plan_result["action_type"],
reasoning=plan_result["reasoning"],
action_data=plan_result["action_data"],
cycle_timers=cycle_timers,
thinking_id=thinking_id,
)
try:
action_taken, action_command, action_reason = await asyncio.wait_for(
self._handle_action(
action=plan_result["action_type"],
reasoning=plan_result["reasoning"],
action_data=plan_result["action_data"],
cycle_timers=cycle_timers,
thinking_id=thinking_id,
),
timeout=global_config.focus_chat.processor_max_time * 2 # 动作执行允许更长时间
)
except asyncio.TimeoutError:
logger.error(f"{self.log_prefix} 动作执行超时")
action_taken, action_command, action_reason = False, "no_reply", "执行超时"
loop_action_info = {
"action_taken": action_taken,
@ -546,10 +591,17 @@ class HeartFChatting:
"loop_plan_info": loop_plan_info,
"loop_action_info": loop_action_info,
}
except Exception as e:
logger.error(f"{self.log_prefix} 循环处理出错: {e}")
traceback.print_exc()
raise
# 返回一个有效的错误状态
return {
"loop_observation_info": {"observations": []},
"loop_processor_info": {"all_plan_info": [], "processor_time_costs": {}},
"loop_plan_info": {"action_result": {"action_type": "no_reply", "action_data": {}, "reasoning": str(e)}},
"loop_action_info": {"action_taken": False, "command": "error", "reason": str(e)},
}
async def _handle_action(
self,