ruff format
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import time
|
||||
import os
|
||||
from typing import List, Optional, Dict, Any
|
||||
from typing import Optional, Dict, Any
|
||||
|
||||
log_dir = "log/log_cycle_debug/"
|
||||
|
||||
|
||||
class CycleDetail:
|
||||
"""循环信息记录类"""
|
||||
|
||||
@@ -23,35 +24,40 @@ class CycleDetail:
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""将循环信息转换为字典格式"""
|
||||
|
||||
def convert_to_serializable(obj, depth=0, seen=None):
|
||||
if seen is None:
|
||||
seen = set()
|
||||
|
||||
|
||||
# 防止递归过深
|
||||
if depth > 5: # 降低递归深度限制
|
||||
return str(obj)
|
||||
|
||||
|
||||
# 防止循环引用
|
||||
obj_id = id(obj)
|
||||
if obj_id in seen:
|
||||
return str(obj)
|
||||
seen.add(obj_id)
|
||||
|
||||
|
||||
try:
|
||||
if hasattr(obj, 'to_dict'):
|
||||
if hasattr(obj, "to_dict"):
|
||||
# 对于有to_dict方法的对象,直接调用其to_dict方法
|
||||
return obj.to_dict()
|
||||
elif isinstance(obj, dict):
|
||||
# 对于字典,只保留基本类型和可序列化的值
|
||||
return {k: convert_to_serializable(v, depth + 1, seen)
|
||||
for k, v in obj.items()
|
||||
if isinstance(k, (str, int, float, bool))}
|
||||
return {
|
||||
k: convert_to_serializable(v, depth + 1, seen)
|
||||
for k, v in obj.items()
|
||||
if isinstance(k, (str, int, float, bool))
|
||||
}
|
||||
elif isinstance(obj, (list, tuple)):
|
||||
# 对于列表和元组,只保留可序列化的元素
|
||||
return [convert_to_serializable(item, depth + 1, seen)
|
||||
for item in obj
|
||||
if not isinstance(item, (dict, list, tuple)) or
|
||||
isinstance(item, (str, int, float, bool, type(None)))]
|
||||
return [
|
||||
convert_to_serializable(item, depth + 1, seen)
|
||||
for item in obj
|
||||
if not isinstance(item, (dict, list, tuple))
|
||||
or isinstance(item, (str, int, float, bool, type(None)))
|
||||
]
|
||||
elif isinstance(obj, (str, int, float, bool, type(None))):
|
||||
return obj
|
||||
else:
|
||||
@@ -74,19 +80,19 @@ class CycleDetail:
|
||||
def complete_cycle(self):
|
||||
"""完成循环,记录结束时间"""
|
||||
self.end_time = time.time()
|
||||
|
||||
|
||||
# 处理 prefix,只保留中英文字符
|
||||
if not self.prefix:
|
||||
self.prefix = "group"
|
||||
else:
|
||||
# 只保留中文和英文字符
|
||||
self.prefix = ''.join(char for char in self.prefix if '\u4e00' <= char <= '\u9fff' or char.isascii())
|
||||
self.prefix = "".join(char for char in self.prefix if "\u4e00" <= char <= "\u9fff" or char.isascii())
|
||||
if not self.prefix:
|
||||
self.prefix = "group"
|
||||
|
||||
|
||||
current_time_minute = time.strftime("%Y%m%d_%H%M", time.localtime())
|
||||
self.log_cycle_to_file(log_dir + self.prefix + f"/{current_time_minute}_cycle_" + str(self.cycle_id) + ".json")
|
||||
|
||||
|
||||
def log_cycle_to_file(self, file_path: str):
|
||||
"""将循环信息写入文件"""
|
||||
# 如果目录不存在,则创建目录
|
||||
@@ -95,6 +101,7 @@ class CycleDetail:
|
||||
os.makedirs(dir_name, exist_ok=True)
|
||||
# 写入文件
|
||||
import json
|
||||
|
||||
with open(file_path, "a", encoding="utf-8") as f:
|
||||
f.write(json.dumps(self.to_dict(), ensure_ascii=False) + "\n")
|
||||
|
||||
|
||||
@@ -418,7 +418,9 @@ class HeartFChatting:
|
||||
# 记录耗时
|
||||
processor_time_costs[processor_name] = duration_since_parallel_start
|
||||
except asyncio.TimeoutError:
|
||||
logger.info(f"{self.log_prefix} 处理器 {processor_name} 超时(>{global_config.focus_chat.processor_max_time}s),已跳过")
|
||||
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(
|
||||
@@ -462,7 +464,7 @@ class HeartFChatting:
|
||||
}
|
||||
|
||||
self.all_observations = observations
|
||||
|
||||
|
||||
with Timer("调整动作", cycle_timers):
|
||||
# 处理特殊的观察
|
||||
await self.action_modifier.modify_actions(observations=observations)
|
||||
@@ -476,26 +478,24 @@ class HeartFChatting:
|
||||
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)
|
||||
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
|
||||
)
|
||||
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,
|
||||
}
|
||||
|
||||
|
||||
|
||||
with Timer("规划器", cycle_timers):
|
||||
plan_result = await self.action_planner.plan(all_plan_info, running_memorys)
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ class ActionModifier:
|
||||
observations: Optional[List[Observation]] = None,
|
||||
**kwargs: Any,
|
||||
):
|
||||
|
||||
# 处理Observation对象
|
||||
if observations:
|
||||
# action_info = ActionInfo()
|
||||
@@ -163,22 +162,34 @@ class ActionModifier:
|
||||
if len(last_max_reply_num) >= max_reply_num and all(last_max_reply_num):
|
||||
# 如果最近max_reply_num次都是reply,直接移除
|
||||
result["remove"].append("reply")
|
||||
logger.info(f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,直接移除")
|
||||
logger.info(
|
||||
f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,直接移除"
|
||||
)
|
||||
elif len(last_max_reply_num) >= sec_thres_reply_num and all(last_max_reply_num[-sec_thres_reply_num:]):
|
||||
# 如果最近sec_thres_reply_num次都是reply,40%概率移除
|
||||
if random.random() < 0.4 / global_config.focus_chat.consecutive_replies:
|
||||
result["remove"].append("reply")
|
||||
logger.info(f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,{0.4 / global_config.focus_chat.consecutive_replies}概率移除,移除")
|
||||
logger.info(
|
||||
f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,{0.4 / global_config.focus_chat.consecutive_replies}概率移除,移除"
|
||||
)
|
||||
else:
|
||||
logger.debug(f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,{0.4 / global_config.focus_chat.consecutive_replies}概率移除,不移除")
|
||||
logger.debug(
|
||||
f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,{0.4 / global_config.focus_chat.consecutive_replies}概率移除,不移除"
|
||||
)
|
||||
elif len(last_max_reply_num) >= one_thres_reply_num and all(last_max_reply_num[-one_thres_reply_num:]):
|
||||
# 如果最近one_thres_reply_num次都是reply,20%概率移除
|
||||
if random.random() < 0.2 / global_config.focus_chat.consecutive_replies:
|
||||
result["remove"].append("reply")
|
||||
logger.info(f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,{0.2 / global_config.focus_chat.consecutive_replies}概率移除,移除")
|
||||
logger.info(
|
||||
f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,{0.2 / global_config.focus_chat.consecutive_replies}概率移除,移除"
|
||||
)
|
||||
else:
|
||||
logger.debug(f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,{0.2 / global_config.focus_chat.consecutive_replies}概率移除,不移除")
|
||||
logger.debug(
|
||||
f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,{0.2 / global_config.focus_chat.consecutive_replies}概率移除,不移除"
|
||||
)
|
||||
else:
|
||||
logger.debug(f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,无需移除")
|
||||
logger.debug(
|
||||
f"最近{len(last_max_reply_num)}次回复中,有{no_reply_count}次no_reply,{len(last_max_reply_num) - no_reply_count}次reply,无需移除"
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
@@ -42,5 +42,5 @@ class ActionObservation:
|
||||
"observe_id": self.observe_id,
|
||||
"last_observe_time": self.last_observe_time,
|
||||
"all_actions": self.all_actions,
|
||||
"all_using_actions": self.all_using_actions
|
||||
"all_using_actions": self.all_using_actions,
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class ChattingObservation(Observation):
|
||||
"person_list": self.person_list,
|
||||
"oldest_messages_str": self.oldest_messages_str,
|
||||
"compressor_prompt": self.compressor_prompt,
|
||||
"last_observe_time": self.last_observe_time
|
||||
"last_observe_time": self.last_observe_time,
|
||||
}
|
||||
|
||||
async def initialize(self):
|
||||
|
||||
@@ -39,7 +39,7 @@ class HFCloopObservation:
|
||||
responses_for_prompt = []
|
||||
|
||||
cycle_last_reason = ""
|
||||
|
||||
|
||||
# 检查这最近的活动循环中有多少是连续的文本回复 (从最近的开始看)
|
||||
for cycle in recent_active_cycles:
|
||||
action_type = cycle.loop_plan_info["action_result"]["action_type"]
|
||||
@@ -57,29 +57,33 @@ class HFCloopObservation:
|
||||
action_reasoning_str = f"你选择这个action的原因是:{action_reasoning}"
|
||||
else:
|
||||
action_reasoning_str = ""
|
||||
|
||||
|
||||
if action_type == "reply":
|
||||
consecutive_text_replies += 1
|
||||
response_text = cycle.loop_plan_info["action_result"]["action_data"].get("text", "[空回复]")
|
||||
responses_for_prompt.append(response_text)
|
||||
|
||||
|
||||
if is_taken:
|
||||
action_detailed_str += f"{action_taken_time_str}时,你选择回复(action:{action_type},内容是:'{response_text}')。{action_reasoning_str}\n"
|
||||
else:
|
||||
action_detailed_str += f"{action_taken_time_str}时,你选择回复(action:{action_type},内容是:'{response_text}'),但是动作失败了。{action_reasoning_str}\n"
|
||||
elif action_type == "no_reply":
|
||||
action_detailed_str += f"{action_taken_time_str}时,你选择不回复(action:{action_type}),{action_reasoning_str}\n"
|
||||
action_detailed_str += (
|
||||
f"{action_taken_time_str}时,你选择不回复(action:{action_type}),{action_reasoning_str}\n"
|
||||
)
|
||||
else:
|
||||
if is_taken:
|
||||
action_detailed_str += f"{action_taken_time_str}时,你选择执行了(action:{action_type}),{action_reasoning_str}\n"
|
||||
action_detailed_str += (
|
||||
f"{action_taken_time_str}时,你选择执行了(action:{action_type}),{action_reasoning_str}\n"
|
||||
)
|
||||
else:
|
||||
action_detailed_str += f"{action_taken_time_str}时,你选择执行了(action:{action_type}),但是动作失败了。{action_reasoning_str}\n"
|
||||
|
||||
|
||||
if action_detailed_str:
|
||||
cycle_info_block = f"\n你最近做的事:\n{action_detailed_str}\n"
|
||||
else:
|
||||
cycle_info_block = "\n"
|
||||
|
||||
|
||||
# 根据连续文本回复的数量构建提示信息
|
||||
if consecutive_text_replies >= 3: # 如果最近的三个活动都是文本回复
|
||||
cycle_info_block = f'你已经连续回复了三条消息(最近: "{responses_for_prompt[0]}",第二近: "{responses_for_prompt[1]}",第三近: "{responses_for_prompt[2]}")。你回复的有点多了,请注意'
|
||||
@@ -116,5 +120,5 @@ class HFCloopObservation:
|
||||
"observe_id": self.observe_id,
|
||||
"last_observe_time": self.last_observe_time,
|
||||
# 不序列化history_loop,避免循环引用
|
||||
"history_loop_count": len(self.history_loop)
|
||||
"history_loop_count": len(self.history_loop),
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ class Observation:
|
||||
return {
|
||||
"observe_info": self.observe_info,
|
||||
"observe_id": self.observe_id,
|
||||
"last_observe_time": self.last_observe_time
|
||||
"last_observe_time": self.last_observe_time,
|
||||
}
|
||||
|
||||
async def observe(self):
|
||||
|
||||
@@ -22,7 +22,7 @@ class StructureObservation:
|
||||
"observe_id": self.observe_id,
|
||||
"last_observe_time": self.last_observe_time,
|
||||
"history_loop": self.history_loop,
|
||||
"structured_info": self.structured_info
|
||||
"structured_info": self.structured_info,
|
||||
}
|
||||
|
||||
def get_observe_info(self):
|
||||
|
||||
@@ -39,6 +39,10 @@ class WorkingMemoryObservation:
|
||||
"observe_info": self.observe_info,
|
||||
"observe_id": self.observe_id,
|
||||
"last_observe_time": self.last_observe_time,
|
||||
"working_memory": self.working_memory.to_dict() if hasattr(self.working_memory, 'to_dict') else str(self.working_memory),
|
||||
"retrieved_working_memory": [item.to_dict() if hasattr(item, 'to_dict') else str(item) for item in self.retrieved_working_memory]
|
||||
"working_memory": self.working_memory.to_dict()
|
||||
if hasattr(self.working_memory, "to_dict")
|
||||
else str(self.working_memory),
|
||||
"retrieved_working_memory": [
|
||||
item.to_dict() if hasattr(item, "to_dict") else str(item) for item in self.retrieved_working_memory
|
||||
],
|
||||
}
|
||||
|
||||
@@ -146,10 +146,10 @@ class FocusChatConfig(ConfigBase):
|
||||
|
||||
consecutive_replies: float = 1
|
||||
"""连续回复能力,值越高,麦麦连续回复的概率越高"""
|
||||
|
||||
|
||||
parallel_processing: bool = False
|
||||
"""是否允许处理器阶段和回忆阶段并行执行"""
|
||||
|
||||
|
||||
processor_max_time: int = 25
|
||||
"""处理器最大时间,单位秒,如果超过这个时间,处理器会自动停止"""
|
||||
|
||||
@@ -166,13 +166,11 @@ class FocusChatProcessorConfig(ConfigBase):
|
||||
|
||||
working_memory_processor: bool = True
|
||||
"""是否启用工作记忆处理器"""
|
||||
|
||||
|
||||
lite_chat_mind_processor: bool = False
|
||||
"""是否启用轻量级聊天思维处理器,可以节省token消耗和时间"""
|
||||
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class ExpressionConfig(ConfigBase):
|
||||
"""表达配置类"""
|
||||
|
||||
@@ -753,7 +753,7 @@ class LLMRequest:
|
||||
|
||||
response = await self._execute_request(endpoint="/chat/completions", payload=data, prompt=prompt)
|
||||
# 原样返回响应,不做处理
|
||||
|
||||
|
||||
if len(response) == 3:
|
||||
content, reasoning_content, tool_calls = response
|
||||
return content, (reasoning_content, self.model_name, tool_calls)
|
||||
|
||||
Reference in New Issue
Block a user