diff --git a/src/chat/normal_chat/normal_chat.py b/src/chat/normal_chat/normal_chat.py index c616d3cc6..632c40792 100644 --- a/src/chat/normal_chat/normal_chat.py +++ b/src/chat/normal_chat/normal_chat.py @@ -183,7 +183,7 @@ class NormalChat: self.adjust_reply_frequency(duration=(time.time() - self.start_time) / 60) # print(self.engaging_persons) - + await self.normal_response( message=message, is_mentioned=is_mentioned, @@ -229,7 +229,7 @@ class NormalChat: # 更新engaging_persons统计信息 self._update_engaging_person_stats(message, is_reply=False) - + # 检查是否有用户满足关系构建条件 asyncio.create_task(self._check_relation_building_conditions()) @@ -426,7 +426,7 @@ class NormalChat: if first_bot_msg: # 更新engaging_persons统计信息 - 标记为回复 self._update_engaging_person_stats(message, is_reply=True) - + # 记录回复信息到最近回复列表中 reply_info = { "time": time.time(), @@ -671,27 +671,31 @@ class NormalChat: user_id = message.message_info.user_info.user_id person_id = PersonInfoManager.get_person_id(platform, user_id) current_time = time.time() - + if person_id not in self.engaging_persons: self.engaging_persons[person_id] = { "first_time": current_time, "last_time": current_time, "receive_count": 0, "reply_count": 0, - "relation_built": False + "relation_built": False, } - + if is_reply: self.engaging_persons[person_id]["reply_count"] += 1 - logger.debug(f"[{self.stream_name}] 用户 {person_id} 回复次数更新: {self.engaging_persons[person_id]['reply_count']}") + logger.debug( + f"[{self.stream_name}] 用户 {person_id} 回复次数更新: {self.engaging_persons[person_id]['reply_count']}" + ) else: self.engaging_persons[person_id]["receive_count"] += 1 self.engaging_persons[person_id]["last_time"] = current_time - logger.debug(f"[{self.stream_name}] 用户 {person_id} 消息次数更新: {self.engaging_persons[person_id]['receive_count']}") + logger.debug( + f"[{self.stream_name}] 用户 {person_id} 消息次数更新: {self.engaging_persons[person_id]['receive_count']}" + ) def get_engaging_persons(self) -> dict: """获取所有engaging_persons统计信息 - + Returns: dict: person_id -> {first_time, last_time, receive_count, reply_count} """ @@ -699,10 +703,10 @@ class NormalChat: def get_engaging_person_stats(self, person_id: str) -> dict: """获取特定用户的统计信息 - + Args: person_id: 用户ID - + Returns: dict: 用户统计信息,如果用户不存在则返回None """ @@ -710,23 +714,19 @@ class NormalChat: def get_top_engaging_persons(self, limit: int = 10, sort_by: str = "receive_count") -> list: """获取最活跃的用户列表 - + Args: limit: 返回的用户数量限制 sort_by: 排序依据,可选值: "receive_count", "reply_count", "last_time" - + Returns: list: 按指定条件排序的用户列表 """ if sort_by not in ["receive_count", "reply_count", "last_time"]: sort_by = "receive_count" - - sorted_persons = sorted( - self.engaging_persons.items(), - key=lambda x: x[1][sort_by], - reverse=True - ) - + + sorted_persons = sorted(self.engaging_persons.items(), key=lambda x: x[1][sort_by], reverse=True) + return sorted_persons[:limit] def clear_engaging_persons_stats(self): @@ -736,23 +736,20 @@ class NormalChat: def get_relation_building_stats(self) -> dict: """获取关系构建相关统计信息 - + Returns: dict: 关系构建统计信息 """ total_persons = len(self.engaging_persons) - relation_built_count = sum(1 for stats in self.engaging_persons.values() - if stats.get("relation_built", False)) + relation_built_count = sum(1 for stats in self.engaging_persons.values() if stats.get("relation_built", False)) pending_persons = [] - + current_time = time.time() for person_id, stats in self.engaging_persons.items(): if not stats.get("relation_built", False): time_elapsed = current_time - stats["first_time"] - total_messages = self._get_total_messages_in_timerange( - stats["first_time"], stats["last_time"] - ) - + total_messages = self._get_total_messages_in_timerange(stats["first_time"], stats["last_time"]) + # 检查是否接近满足条件 progress_info = { "person_id": person_id, @@ -761,24 +758,24 @@ class NormalChat: "receive_count": stats["receive_count"], "reply_count": stats["reply_count"], "progress": { - "50_messages": f"{total_messages}/50 ({total_messages/50*100:.1f}%)", + "50_messages": f"{total_messages}/50 ({total_messages / 50 * 100:.1f}%)", "35_msg_10min": f"{total_messages}/35 + {time_elapsed}/600s", - "25_msg_30min": f"{total_messages}/25 + {time_elapsed}/1800s", - "10_msg_1hour": f"{total_messages}/10 + {time_elapsed}/3600s" - } + "25_msg_30min": f"{total_messages}/25 + {time_elapsed}/1800s", + "10_msg_1hour": f"{total_messages}/10 + {time_elapsed}/3600s", + }, } pending_persons.append(progress_info) - + return { "total_persons": total_persons, "relation_built_count": relation_built_count, "pending_count": len(pending_persons), - "pending_persons": pending_persons + "pending_persons": pending_persons, } def get_engaging_persons_summary(self) -> dict: """获取engaging_persons统计摘要 - + Returns: dict: 包含总用户数、总消息数、总回复数等统计信息 """ @@ -788,63 +785,54 @@ class NormalChat: "total_messages": 0, "total_replies": 0, "most_active_person": None, - "most_replied_person": None + "most_replied_person": None, } - + total_messages = sum(stats["receive_count"] for stats in self.engaging_persons.values()) total_replies = sum(stats["reply_count"] for stats in self.engaging_persons.values()) - + most_active = max(self.engaging_persons.items(), key=lambda x: x[1]["receive_count"]) most_replied = max(self.engaging_persons.items(), key=lambda x: x[1]["reply_count"]) - + return { "total_persons": len(self.engaging_persons), "total_messages": total_messages, "total_replies": total_replies, - "most_active_person": { - "person_id": most_active[0], - "message_count": most_active[1]["receive_count"] - }, - "most_replied_person": { - "person_id": most_replied[0], - "reply_count": most_replied[1]["reply_count"] - } + "most_active_person": {"person_id": most_active[0], "message_count": most_active[1]["receive_count"]}, + "most_replied_person": {"person_id": most_replied[0], "reply_count": most_replied[1]["reply_count"]}, } async def _check_relation_building_conditions(self): """检查engaging_persons中是否有满足关系构建条件的用户""" current_time = time.time() - + for person_id, stats in list(self.engaging_persons.items()): # 跳过已经进行过关系构建的用户 if stats.get("relation_built", False): continue - + # 计算时间差和消息数量 time_elapsed = current_time - stats["first_time"] - total_messages = self._get_total_messages_in_timerange( - stats["first_time"], stats["last_time"] - ) - + total_messages = self._get_total_messages_in_timerange(stats["first_time"], stats["last_time"]) + # 检查是否满足关系构建条件 should_build_relation = ( total_messages >= 50 # 50条消息必定满足 - or (total_messages >= 35 and time_elapsed >= 600) # 35条且10分钟 + or (total_messages >= 35 and time_elapsed >= 600) # 35条且10分钟 or (total_messages >= 25 and time_elapsed >= 1800) # 25条且30分钟 or (total_messages >= 10 and time_elapsed >= 3600) # 10条且1小时 ) - + if should_build_relation: logger.info( f"[{self.stream_name}] 用户 {person_id} 满足关系构建条件。" f"消息数:{total_messages},时长:{time_elapsed:.0f}秒," f"收到消息:{stats['receive_count']},回复次数:{stats['reply_count']}" ) - + # 计算构建概率并决定是否构建 await self._evaluate_and_build_relation(person_id, stats, total_messages) - def _get_total_messages_in_timerange(self, start_time: float, end_time: float) -> int: """获取指定时间范围内的总消息数量""" try: @@ -858,25 +846,25 @@ class NormalChat: """评估并执行关系构建""" receive_count = stats["receive_count"] reply_count = stats["reply_count"] - + # 计算回复概率(reply_count在总消息中的比值) reply_ratio = reply_count / total_messages if total_messages > 0 else 0 reply_build_probability = reply_ratio # 100%回复则100%构建 - + # 计算接收概率(receive_count的影响) receive_ratio = receive_count / total_messages if total_messages > 0 else 0 receive_build_probability = receive_ratio * 0.25 # 100%接收则25%构建 - + # 取最高概率 final_probability = max(reply_build_probability, receive_build_probability) - + logger.info( f"[{self.stream_name}] 用户 {person_id} 关系构建概率评估:" f"回复比例:{reply_ratio:.2f}({reply_build_probability:.2f})" - f",接收比例:{receive_ratio:.2f}({receive_build_probability:.2f})" + f",接收比例:{receive_ratio:.2f}({receive_build_probability:.2f})" f",最终概率:{final_probability:.2f}" ) - + # 使用随机数决定是否构建关系 if random() < final_probability: logger.info(f"[{self.stream_name}] 决定为用户 {person_id} 构建关系") @@ -892,26 +880,24 @@ class NormalChat: """为特定用户构建关系""" try: start_time = stats["first_time"] - end_time = stats["last_time"] - + end_time = stats["last_time"] + # 获取该时间段的所有消息用于关系构建 messages = get_raw_msg_by_timestamp_with_chat(self.stream_id, start_time, end_time) - + if messages: logger.info(f"[{self.stream_name}] 为用户 {person_id} 获取到 {len(messages)} 条消息用于关系构建") - + # 调用关系管理器更新印象 relationship_manager = get_relationship_manager() await relationship_manager.update_person_impression( - person_id=person_id, - timestamp=end_time, - bot_engaged_messages=messages + person_id=person_id, timestamp=end_time, bot_engaged_messages=messages ) - + logger.info(f"[{self.stream_name}] 用户 {person_id} 关系构建完成") else: logger.warning(f"[{self.stream_name}] 未找到用户 {person_id} 的消息,关系构建跳过") - + except Exception as e: logger.error(f"[{self.stream_name}] 为用户 {person_id} 构建关系时出错: {e}") traceback.print_exc() diff --git a/src/chat/utils/utils_image.py b/src/chat/utils/utils_image.py index 968846d15..83afc76d7 100644 --- a/src/chat/utils/utils_image.py +++ b/src/chat/utils/utils_image.py @@ -382,9 +382,14 @@ class ImageManager: if existing_image: # 检查是否缺少必要字段,如果缺少则创建新记录 - if (not hasattr(existing_image, 'image_id') or not existing_image.image_id or - not hasattr(existing_image, 'count') or existing_image.count is None or - not hasattr(existing_image, 'vlm_processed') or existing_image.vlm_processed is None): + if ( + not hasattr(existing_image, "image_id") + or not existing_image.image_id + or not hasattr(existing_image, "count") + or existing_image.count is None + or not hasattr(existing_image, "vlm_processed") + or existing_image.vlm_processed is None + ): logger.debug(f"图片记录缺少必要字段,补全旧记录: {image_hash}") image_id = str(uuid.uuid4()) else: diff --git a/src/person_info/relationship_manager.py b/src/person_info/relationship_manager.py index 06e19c2fd..faa0c77e5 100644 --- a/src/person_info/relationship_manager.py +++ b/src/person_info/relationship_manager.py @@ -11,7 +11,6 @@ import json from json_repair import repair_json from datetime import datetime from difflib import SequenceMatcher -import ast import jieba from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity @@ -431,9 +430,6 @@ class RelationshipManager: await person_info_manager.update_one_field(person_id, "impression", compressed_summary) - - - compress_short_prompt = f""" 你的名字是{global_config.bot.nickname},{global_config.bot.nickname}的别名是{alias_str}。 请不要混淆你自己和{global_config.bot.nickname}和{person_name}。 @@ -447,19 +443,15 @@ class RelationshipManager: 3.{person_name}的关键信息 请输出一段平文本,以陈诉自白的语气,输出你对{person_name}的概括,不要输出任何其他内容。 """ - compressed_short_summary, _ = await self.relationship_llm.generate_response_async(prompt=compress_short_prompt) + compressed_short_summary, _ = await self.relationship_llm.generate_response_async( + prompt=compress_short_prompt + ) # current_time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S") # compressed_short_summary = f"截至{current_time},你对{person_name}的了解:{compressed_short_summary}" await person_info_manager.update_one_field(person_id, "short_impression", compressed_short_summary) - - - - - - - + forgotten_points = [] # 这句代码的作用是:将更新后的 forgotten_points(遗忘的记忆点)列表,序列化为 JSON 字符串后,写回到数据库中的 forgotten_points 字段