fix:修复神秘问题

This commit is contained in:
SengokuCola
2025-04-25 19:15:15 +08:00
parent 4f919ce15c
commit 75924bf499
4 changed files with 132 additions and 96 deletions

View File

@@ -163,7 +163,7 @@ MOOD_STYLE_CONFIG = {
"console_format": ( "console_format": (
"<white>{time:YYYY-MM-DD HH:mm:ss}</white> | " "<white>{time:YYYY-MM-DD HH:mm:ss}</white> | "
"<level>{level: <8}</level> | " "<level>{level: <8}</level> | "
"</magenta>心情</magenta> | " "<magenta>心情</magenta> | "
"<level>{message}</level>" "<level>{message}</level>"
), ),
"file_format": "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 心情 | {message}", "file_format": "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {extra[module]: <15} | 心情 | {message}",

View File

@@ -24,8 +24,9 @@ emoji_log_config = LogConfig(
logger = get_module_logger("emoji", config=emoji_log_config) logger = get_module_logger("emoji", config=emoji_log_config)
EMOJI_DIR = os.path.join("data", "emoji") # 表情包存储目录 BASE_DIR = os.path.join("data")
EMOJI_REGISTED_DIR = os.path.join("data", "emoji_registed") # 已注册的表情包注册目录 EMOJI_DIR = os.path.join(BASE_DIR, "emoji") # 表情包存储目录
EMOJI_REGISTED_DIR = os.path.join(BASE_DIR, "emoji_registed") # 已注册的表情包注册目录
''' '''
@@ -301,7 +302,7 @@ class EmojiManager:
emoji_similarities.sort(key=lambda x: x[1], reverse=True) emoji_similarities.sort(key=lambda x: x[1], reverse=True)
# 获取前5个最相似的表情包 # 获取前5个最相似的表情包
top_5_emojis = emoji_similarities[:5] if len(emoji_similarities) > 5 else emoji_similarities top_5_emojis = emoji_similarities[:10] if len(emoji_similarities) > 10 else emoji_similarities
if not top_5_emojis: if not top_5_emojis:
logger.warning("未找到匹配的表情包") logger.warning("未找到匹配的表情包")
@@ -398,6 +399,7 @@ class EmojiManager:
while True: while True:
logger.info("[扫描] 开始检查表情包完整性...") logger.info("[扫描] 开始检查表情包完整性...")
await self.check_emoji_file_integrity() await self.check_emoji_file_integrity()
await self.clear_temp_emoji()
logger.info("[扫描] 开始扫描新表情包...") logger.info("[扫描] 开始扫描新表情包...")
# 检查表情包目录是否存在 # 检查表情包目录是否存在
@@ -784,5 +786,42 @@ class EmojiManager:
return False return False
async def clear_temp_emoji(self):
"""每天清理临时表情包
清理/data/emoji和/data/image目录下的所有文件
当目录中文件数超过50时会全部删除
"""
logger.info("[清理] 开始清理临时表情包...")
# 清理emoji目录
emoji_dir = os.path.join(BASE_DIR, "emoji")
if os.path.exists(emoji_dir):
files = os.listdir(emoji_dir)
# 如果文件数超过50就全部删除
if len(files) > 50:
for filename in files:
file_path = os.path.join(emoji_dir, filename)
if os.path.isfile(file_path):
os.remove(file_path)
logger.debug(f"[清理] 删除表情包文件: {filename}")
# 清理image目录
image_dir = os.path.join(BASE_DIR, "image")
if os.path.exists(image_dir):
files = os.listdir(image_dir)
# 如果文件数超过50就全部删除
if len(files) > 50:
for filename in files:
file_path = os.path.join(image_dir, filename)
if os.path.isfile(file_path):
os.remove(file_path)
logger.debug(f"[清理] 删除图片文件: {filename}")
logger.success("[清理] 临时文件清理完成")
# 创建全局单例 # 创建全局单例
emoji_manager = EmojiManager() emoji_manager = EmojiManager()

View File

@@ -344,51 +344,48 @@ class HeartFChatting:
cycle_timers = {} cycle_timers = {}
loop_cycle_start_time = time.monotonic() loop_cycle_start_time = time.monotonic()
with Timer("Total Cycle", cycle_timers): # 执行规划和处理阶段
# 执行规划和处理阶段 async with self._get_cycle_context() as acquired_lock:
async with self._get_cycle_context() as acquired_lock: if not acquired_lock:
if not acquired_lock: continue
continue
# 记录规划开始时间点 # 记录规划开始时间点
planner_start_db_time = time.time() planner_start_db_time = time.time()
# 执行规划阶段 # 执行规划阶段
with Timer("Planning Phase", cycle_timers): action_taken, thinking_id = await self._think_plan_execute_loop(
action_taken, thinking_id = await self._think_plan_execute( cycle_timers, planner_start_db_time
cycle_timers, planner_start_db_time
)
# 更新循环信息
self._current_cycle.set_thinking_id(thinking_id)
self._current_cycle.timers = cycle_timers
# 防止循环过快消耗资源
with Timer("Cycle Delay", cycle_timers):
await self._handle_cycle_delay(action_taken, loop_cycle_start_time, self.log_prefix)
# 等待直到所有消息都发送完成
with Timer("Wait Messages Complete", cycle_timers):
while await self._should_skip_cycle(thinking_id):
await asyncio.sleep(0.2)
# 完成当前循环并保存历史
self._current_cycle.complete_cycle()
self._cycle_history.append(self._current_cycle)
# 记录循环信息和计时器结果
timer_strings = []
for name, elapsed in cycle_timers.items():
formatted_time = f"{elapsed * 1000:.2f}毫秒" if elapsed < 1 else f"{elapsed:.2f}"
timer_strings.append(f"{name}: {formatted_time}")
logger.debug(
f"{self.log_prefix} 循环 #{self._current_cycle.cycle_id} 完成, "
f"耗时: {self._current_cycle.end_time - self._current_cycle.start_time:.2f}秒, "
f"动作: {self._current_cycle.action_type}"
+ (f"\n计时器详情: {'; '.join(timer_strings)}" if timer_strings else "")
) )
# 更新循环信息
self._current_cycle.set_thinking_id(thinking_id)
self._current_cycle.timers = cycle_timers
# 防止循环过快消耗资源
await self._handle_cycle_delay(action_taken, loop_cycle_start_time, self.log_prefix)
# 等待直到所有消息都发送完成
with Timer("发送消息", cycle_timers):
while await self._should_skip_cycle(thinking_id):
await asyncio.sleep(0.2)
# 完成当前循环并保存历史
self._current_cycle.complete_cycle()
self._cycle_history.append(self._current_cycle)
# 记录循环信息和计时器结果
timer_strings = []
for name, elapsed in cycle_timers.items():
formatted_time = f"{elapsed * 1000:.2f}毫秒" if elapsed < 1 else f"{elapsed:.2f}"
timer_strings.append(f"{name}: {formatted_time}")
logger.debug(
f"{self.log_prefix} 第 #{self._current_cycle.cycle_id}次思考完成,"
f"耗时: {self._current_cycle.end_time - self._current_cycle.start_time:.2f}秒, "
f"动作: {self._current_cycle.action_type}"
+ (f"\n计时器详情: {'; '.join(timer_strings)}" if timer_strings else "")
)
except asyncio.CancelledError: except asyncio.CancelledError:
logger.info(f"{self.log_prefix} HeartFChatting: 麦麦的激情水群(HFC)被取消了") logger.info(f"{self.log_prefix} HeartFChatting: 麦麦的激情水群(HFC)被取消了")
except Exception as e: except Exception as e:
@@ -434,22 +431,22 @@ class HeartFChatting:
logger.error(f"{self.log_prefix} 检查新消息时出错: {e}") logger.error(f"{self.log_prefix} 检查新消息时出错: {e}")
return False return False
async def _think_plan_execute( async def _think_plan_execute_loop(
self, cycle_timers: dict, planner_start_db_time: float self, cycle_timers: dict, planner_start_db_time: float
) -> tuple[bool, str]: ) -> tuple[bool, str]:
"""执行规划阶段""" """执行规划阶段"""
try: try:
# 获取子思维思考结果 # 获取子思维思考结果
current_mind = "" current_mind = ""
with Timer("SubMind Thinking", cycle_timers): with Timer("思考", cycle_timers):
current_mind = await self._get_submind_thinking() current_mind = await self._get_submind_thinking()
# 记录子思维思考内容 # 记录子思维思考内容
if self._current_cycle: if self._current_cycle:
self._current_cycle.set_response_info(sub_mind_thinking=current_mind) self._current_cycle.set_response_info(sub_mind_thinking=current_mind)
# 执行规划 # 执行规划
with Timer("Planner", cycle_timers): with Timer("决策", cycle_timers):
planner_result = await self._planner(current_mind) planner_result = await self._planner(current_mind, cycle_timers)
# 在获取规划结果后检查新消息 # 在获取规划结果后检查新消息
if await self._check_new_messages(planner_start_db_time): if await self._check_new_messages(planner_start_db_time):
@@ -471,7 +468,8 @@ class HeartFChatting:
return False, "" return False, ""
# 根据动作类型执行对应处理 # 根据动作类型执行对应处理
return await self._handle_action(action, reasoning, planner_result.get("emoji_query", ""), cycle_timers, planner_start_db_time) with Timer("执行", cycle_timers):
return await self._handle_action(action, reasoning, planner_result.get("emoji_query", ""), cycle_timers, planner_start_db_time)
except PlannerError as e: except PlannerError as e:
logger.error(f"{self.log_prefix} 规划错误: {e}") logger.error(f"{self.log_prefix} 规划错误: {e}")
@@ -684,8 +682,8 @@ class HeartFChatting:
): ):
"""处理循环延迟""" """处理循环延迟"""
cycle_duration = time.monotonic() - cycle_start_time cycle_duration = time.monotonic() - cycle_start_time
if cycle_duration > 0.1: # if cycle_duration > 0.1:
logger.debug(f"{log_prefix} HeartFChatting: 周期耗时 {cycle_duration:.2f}s.") # logger.debug(f"{log_prefix} HeartFChatting: 周期耗时 {cycle_duration:.2f}s.")
try: try:
sleep_duration = 0.0 sleep_duration = 0.0
@@ -718,7 +716,7 @@ class HeartFChatting:
logger.error(traceback.format_exc()) logger.error(traceback.format_exc())
return "[思考时出错]" return "[思考时出错]"
async def _planner(self, current_mind: str) -> Dict[str, Any]: async def _planner(self, current_mind: str, cycle_timers: dict) -> Dict[str, Any]:
""" """
规划器 (Planner): 使用LLM根据上下文决定是否和如何回复。 规划器 (Planner): 使用LLM根据上下文决定是否和如何回复。
@@ -727,14 +725,11 @@ class HeartFChatting:
""" """
logger.info(f"{self.log_prefix}[Planner] 开始执行规划器") logger.info(f"{self.log_prefix}[Planner] 开始执行规划器")
planner_timers = {} # 用于存储各阶段计时结果
# 获取观察信息 # 获取观察信息
with Timer("获取观察信息", planner_timers): observation = self.observations[0]
observation = self.observations[0] # await observation.observe()
# await observation.observe() observed_messages = observation.talking_message
observed_messages = observation.talking_message observed_messages_str = observation.talking_message_str
observed_messages_str = observation.talking_message_str
# --- 使用 LLM 进行决策 --- # # --- 使用 LLM 进行决策 --- #
action = "no_reply" # 默认动作 action = "no_reply" # 默认动作
@@ -744,7 +739,7 @@ class HeartFChatting:
try: try:
# 构建提示词 # 构建提示词
with Timer("构建提示词", planner_timers): with Timer("构建提示词", cycle_timers):
prompt = await self._build_planner_prompt( prompt = await self._build_planner_prompt(
observed_messages_str, current_mind, self.sub_mind.structured_info observed_messages_str, current_mind, self.sub_mind.structured_info
) )
@@ -756,7 +751,7 @@ class HeartFChatting:
} }
# 执行LLM请求 # 执行LLM请求
with Timer("LLM请求", planner_timers): with Timer("LLM回复", cycle_timers):
try: try:
response = await self.planner_llm._execute_request( response = await self.planner_llm._execute_request(
endpoint="/chat/completions", payload=payload, prompt=prompt endpoint="/chat/completions", payload=payload, prompt=prompt
@@ -773,7 +768,7 @@ class HeartFChatting:
} }
# 处理LLM响应 # 处理LLM响应
with Timer("处理LLM响应", planner_timers): with Timer("使用工具", cycle_timers):
# 使用辅助函数处理工具调用响应 # 使用辅助函数处理工具调用响应
success, arguments, error_msg = process_llm_tool_response( success, arguments, error_msg = process_llm_tool_response(
response, expected_tool_name="decide_reply_action", log_prefix=f"{self.log_prefix}[Planner] " response, expected_tool_name="decide_reply_action", log_prefix=f"{self.log_prefix}[Planner] "

View File

@@ -144,41 +144,43 @@ async def test_without_tool_calls():
# 简单的测试提示词(与工具调用相同,以便公平比较) # 简单的测试提示词(与工具调用相同,以便公平比较)
prompt = """ prompt = """
你的名字是麦麦你包容开放情绪敏感有时候有些搞怪幽默, 是一个学习心理学和脑科学的女大学生现在在读大二你会刷贴吧有时候会想瑟瑟喜欢刷小红书 你的名字是麦麦你包容开放情绪敏感有时候有些搞怪幽默, 是一个学习心理学和脑科学的女大学生现在在读大二你会刷贴吧有时候会喜欢说一些奇怪的话喜欢刷小红书
刚刚你的想法是 刚刚你的内心想法是漂移菌提到罐罐被吃完了可以顺着这个梗继续玩一下比如假装委屈那今晚的加班费是不是也要被吃掉了或者猫娘罢工警告不过薯薯和薯宝之前已经接了不少梗漂移菌刚刚也参与了可能话题热度还在可以再互动一下如果没人接话或许可以问问大家有没有遇到过类似代码写完但奖励被吃掉的搞笑职场经历换个轻松的话题方向
我是麦麦我想('小千石问3.8和3.11谁大已经简单回答了3.11大,现在可以继续聊猫猫头表情包,毕竟大家好像对版本问题兴趣不大,而且猫猫头的话题更轻松有趣。', '')
-----------------------------------
现在是2025-04-24 12:37:00你正在上网和qq群里的网友们聊天群里正在聊的话题是
2025-04-24 12:33:00既文横 :这条调试消息是napcat控制台输出的还是麦麦log输出的;
2025-04-24 12:33:23麦麦() :应该是napcat吧;
2025-04-24 12:33:24麦麦() :[表达了害羞害羞];
2025-04-24 12:33:25兔伽兔伽 :就打开麦麦的那个终端发的呀;
2025-04-24 12:33:45既文横 :那应该不是napcat输出的是麦麦输出的消息怀疑版本问题;
2025-04-24 12:34:02兔伽兔伽 :版本05.15;
2025-04-24 12:34:07麦麦() :话说你们最近刷贴吧看到那个猫猫头表情包了吗;
2025-04-24 12:34:07麦麦() :笑死;
2025-04-24 12:34:08麦麦() :[表达了惊讶搞笑];
2025-04-24 12:34:14兔伽兔伽 :只开一个终端;
2025-04-24 12:35:45兔伽兔伽 :回复既文横的消息(怀疑版本问题)因为之前你连模型的那个我用的了;
2025-04-24 12:35:56麦麦() :那个猫猫头真的魔性;
2025-04-24 12:35:56麦麦() :我存了一堆;
2025-04-24 12:35:56麦麦() :[表达了温馨宠爱];
2025-04-24 12:36:03小千石 :麦麦3.8和3.11谁大;
2025-04-24 12:36:22麦麦() :真的魔性那个猫猫头;
2025-04-24 12:36:22麦麦() :[表达了害羞可爱];
2025-04-24 12:36:43麦麦() :3.11大啦;
2025-04-24 12:36:43麦麦() :[表达了害羞可爱];
--- 以上消息已读 (标记时间: 2025-04-24 12:36:43) --- 暂时不需要使用工具
--- 请关注你上次思考之后以下的新消息--- -----------------------------------
2025-04-24 12:36:53墨墨 :[表情包开心满足]; 现在是2025-04-25 17:38:37你正在上网和qq群里的网友们聊天以下是正在进行的聊天内容
2025-04-25 17:34:08麦麦() :[表达了顽皮嬉戏];
2025-04-25 17:34:39漂移菌 :@麦麦id:3936257206 你是一只猫娘;
2025-04-25 17:34:42薯宝 :🤣;
2025-04-25 17:34:43麦麦() :行啊 工资分我一半;
2025-04-25 17:34:43麦麦() :我帮你写bug;
2025-04-25 17:34:43麦麦() :[表达了悲伤绝望无奈无力];
2025-04-25 17:34:53薯薯 :;
2025-04-25 17:35:03既文横 :麦麦你是一只猫娘程序员猫娘是不需要工资;
2025-04-25 17:35:20薯宝 :[图片图片内容一只卡通风格的灰色猫咪眼睛闭着表情显得很平静图片下方有死了两个字
图片含义猜测这可能是一个幽默的表达用来形容某人或某事处于非常平静的状态仿佛已经了一样] hfc这周真能出来吗...;
2025-04-25 17:35:34薯宝 :[表情包搞笑滑稽讽刺幽默];
2025-04-25 17:36:25麦麦() :喵喵;
2025-04-25 17:36:25麦麦() :代码写完了;
2025-04-25 17:36:25麦麦() :罐罐拿来;
2025-04-25 17:36:25麦麦() :[表达了悲伤绝望无奈无力];
2025-04-25 17:36:41薯薯 :好可爱;
2025-04-25 17:37:05薯薯 :脑补出来认真营业了一天等待主人发放奖励的小猫咪;
2025-04-25 17:37:25薯宝 :敷衍营业bushi;
2025-04-25 17:37:54漂移菌 :回复麦麦的消息(罐罐拿来)猫娘我昨晚上太饿吃完了;
--- 以上消息已读 (标记时间: 2025-04-25 17:37:54) ---
--- 以下新消息未读---
2025-04-25 17:38:29麦麦() :那今晚的猫条是不是也要被克扣了;
2025-04-25 17:38:29麦麦() :[表达了幽默自嘲无奈父子关系编程笑话];
你现在当前心情平静 你现在当前心情平静
现在请你根据刚刚的想法继续思考思考时可以想想如何对群聊内容进行回复要不要对群里的话题进行回复关注新话题可以适当转换话题大家正在说的话才是聊天的主题 现在请你生成你的内心想法要求思考群里正在进行的话题之前大家聊过的话题群里成员的关系请你思考要不要对群里的话题进行回复以及如何对群聊内容进行回复
回复的要求是平淡一些简短一些说中文如果你要回复最好只回复一个人的一个话题 回复的要求是不要总是重复自己提到过的话题如果你要回复最好只回复一个人的一个话题
请注意不要输出多余内容(包括前后缀冒号和引号括号 表情)不要带有括号和动作描写不要回复自己的发言尽量不要说你说过的话 如果最后一条消息是你自己发的观察到的内容只有你自己的发言并且之后没有人回复你不要回复如果聊天记录中最新的消息是你自己发送的并且你还想继续回复你应该紧紧衔接你发送的消息进行话题的深入补充或追问等等请注意不要输出多余内容(包括前后缀冒号和引号括号 表情)不要回复自己的发言
现在请你继续生成你在这个聊天中的想法在原来想法的基础上继续思考不要分点输出,生成内心想法文字不要浮夸 现在请你先输出想法生成你在这个聊天中的想法在原来想法上尝试新的话题不要分点输出,文字不要浮夸在输出完想法请你思考应该使用什么工具工具可以帮你取得一些你不知道的信息或者进行一些操作如果你需要做某件事来对消息和你的回复进行处理请使用工具"""
在输出完想法后请你思考应该使用什么工具如果你需要做某件事来对消息和你的回复进行处理请使用工具"""
# 发送不带工具调用的请求 # 发送不带工具调用的请求
response, reasoning_content = await llm_model.generate_response_async(prompt) response, reasoning_content = await llm_model.generate_response_async(prompt)