This commit is contained in:
SengokuCola
2025-06-14 22:11:16 +08:00
3 changed files with 38 additions and 39 deletions

View File

@@ -183,7 +183,7 @@ class NormalChat:
self.adjust_reply_frequency(duration=(time.time() - self.start_time) / 60) self.adjust_reply_frequency(duration=(time.time() - self.start_time) / 60)
# print(self.engaging_persons) # print(self.engaging_persons)
await self.normal_response( await self.normal_response(
message=message, message=message,
is_mentioned=is_mentioned, is_mentioned=is_mentioned,
@@ -229,7 +229,7 @@ class NormalChat:
# 更新engaging_persons统计信息 # 更新engaging_persons统计信息
self._update_engaging_person_stats(message, is_reply=False) self._update_engaging_person_stats(message, is_reply=False)
# 检查是否有用户满足关系构建条件 # 检查是否有用户满足关系构建条件
asyncio.create_task(self._check_relation_building_conditions()) asyncio.create_task(self._check_relation_building_conditions())
@@ -426,7 +426,7 @@ class NormalChat:
if first_bot_msg: if first_bot_msg:
# 更新engaging_persons统计信息 - 标记为回复 # 更新engaging_persons统计信息 - 标记为回复
self._update_engaging_person_stats(message, is_reply=True) self._update_engaging_person_stats(message, is_reply=True)
# 记录回复信息到最近回复列表中 # 记录回复信息到最近回复列表中
reply_info = { reply_info = {
"time": time.time(), "time": time.time(),
@@ -671,29 +671,33 @@ class NormalChat:
user_id = message.message_info.user_info.user_id user_id = message.message_info.user_info.user_id
person_id = PersonInfoManager.get_person_id(platform, user_id) person_id = PersonInfoManager.get_person_id(platform, user_id)
current_time = time.time() current_time = time.time()
if person_id not in self.engaging_persons: if person_id not in self.engaging_persons:
self.engaging_persons[person_id] = { self.engaging_persons[person_id] = {
"first_time": current_time, "first_time": current_time,
"last_time": current_time, "last_time": current_time,
"receive_count": 0, "receive_count": 0,
"reply_count": 0, "reply_count": 0,
"relation_built": False "relation_built": False,
} }
if is_reply: if is_reply:
self.engaging_persons[person_id]["reply_count"] += 1 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: else:
self.engaging_persons[person_id]["receive_count"] += 1 self.engaging_persons[person_id]["receive_count"] += 1
self.engaging_persons[person_id]["last_time"] = current_time 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']}"
)
async def _check_relation_building_conditions(self): async def _check_relation_building_conditions(self):
"""检查engaging_persons中是否有满足关系构建条件的用户""" """检查engaging_persons中是否有满足关系构建条件的用户"""
current_time = time.time() current_time = time.time()
for person_id, stats in list(self.engaging_persons.items()): for person_id, stats in list(self.engaging_persons.items()):
# 计算时间差和消息数量 # 计算时间差和消息数量
time_elapsed = current_time - stats["first_time"] time_elapsed = current_time - stats["first_time"]
@@ -706,18 +710,18 @@ class NormalChat:
# 检查是否满足关系构建条件 # 检查是否满足关系构建条件
should_build_relation = ( should_build_relation = (
total_messages >= 50 # 50条消息必定满足 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 >= 25 and time_elapsed >= 1800) # 25条且30分钟
or (total_messages >= 10 and time_elapsed >= 3600) # 10条且1小时 or (total_messages >= 10 and time_elapsed >= 3600) # 10条且1小时
) )
if should_build_relation: if should_build_relation:
logger.info( logger.info(
f"[{self.stream_name}] 用户 {person_id} 满足关系构建条件。" f"[{self.stream_name}] 用户 {person_id} 满足关系构建条件。"
f"消息数:{total_messages},时长:{time_elapsed:.0f}秒," f"消息数:{total_messages},时长:{time_elapsed:.0f}秒,"
f"收到消息:{stats['receive_count']},回复次数:{stats['reply_count']}" f"收到消息:{stats['receive_count']},回复次数:{stats['reply_count']}"
) )
# 计算构建概率并决定是否构建 # 计算构建概率并决定是否构建
await self._evaluate_and_build_relation(person_id, stats, total_messages) await self._evaluate_and_build_relation(person_id, stats, total_messages)
@@ -741,7 +745,7 @@ class NormalChat:
receive_count = stats["receive_count"] receive_count = stats["receive_count"]
reply_count = stats["reply_count"] reply_count = stats["reply_count"]
# 计算回复概率reply_count在总消息中的比值 # 计算回复概率reply_count在总消息中的比值
reply_ratio = reply_count / total_messages if total_messages > 0 else 0 reply_ratio = reply_count / total_messages if total_messages > 0 else 0
# 使用对数函数让低比率时概率上升更快log(1 + ratio * k) / log(1 + k) + base # 使用对数函数让低比率时概率上升更快log(1 + ratio * k) / log(1 + k) + base
@@ -759,14 +763,14 @@ class NormalChat:
# 取最高概率 # 取最高概率
final_probability = max(reply_build_probability, receive_build_probability) final_probability = max(reply_build_probability, receive_build_probability)
logger.info( logger.info(
f"[{self.stream_name}] 用户 {person_id} 关系构建概率评估:" f"[{self.stream_name}] 用户 {person_id} 关系构建概率评估:"
f"回复比例:{reply_ratio:.2f}(对数概率:{reply_build_probability:.2f})" 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}" f",最终概率:{final_probability:.2f}"
) )
# 使用随机数决定是否构建关系 # 使用随机数决定是否构建关系
if random() < final_probability: if random() < final_probability:
logger.info(f"[{self.stream_name}] 决定为用户 {person_id} 构建关系") logger.info(f"[{self.stream_name}] 决定为用户 {person_id} 构建关系")
@@ -778,26 +782,24 @@ class NormalChat:
"""为特定用户构建关系""" """为特定用户构建关系"""
try: try:
start_time = stats["first_time"] 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) messages = get_raw_msg_by_timestamp_with_chat(self.stream_id, start_time, end_time)
if messages: if messages:
logger.info(f"[{self.stream_name}] 为用户 {person_id} 获取到 {len(messages)} 条消息用于关系构建") logger.info(f"[{self.stream_name}] 为用户 {person_id} 获取到 {len(messages)} 条消息用于关系构建")
# 调用关系管理器更新印象 # 调用关系管理器更新印象
relationship_manager = get_relationship_manager() relationship_manager = get_relationship_manager()
await relationship_manager.update_person_impression( await relationship_manager.update_person_impression(
person_id=person_id, person_id=person_id, timestamp=end_time, bot_engaged_messages=messages
timestamp=end_time,
bot_engaged_messages=messages
) )
logger.info(f"[{self.stream_name}] 用户 {person_id} 关系构建完成") logger.info(f"[{self.stream_name}] 用户 {person_id} 关系构建完成")
else: else:
logger.warning(f"[{self.stream_name}] 未找到用户 {person_id} 的消息,关系构建跳过") logger.warning(f"[{self.stream_name}] 未找到用户 {person_id} 的消息,关系构建跳过")
except Exception as e: except Exception as e:
logger.error(f"[{self.stream_name}] 为用户 {person_id} 构建关系时出错: {e}") logger.error(f"[{self.stream_name}] 为用户 {person_id} 构建关系时出错: {e}")
traceback.print_exc() traceback.print_exc()

View File

@@ -382,9 +382,14 @@ class ImageManager:
if existing_image: if existing_image:
# 检查是否缺少必要字段,如果缺少则创建新记录 # 检查是否缺少必要字段,如果缺少则创建新记录
if (not hasattr(existing_image, 'image_id') or not existing_image.image_id or if (
not hasattr(existing_image, 'count') or existing_image.count is None or not hasattr(existing_image, "image_id")
not hasattr(existing_image, 'vlm_processed') or existing_image.vlm_processed is None): 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}") logger.debug(f"图片记录缺少必要字段,补全旧记录: {image_hash}")
image_id = str(uuid.uuid4()) image_id = str(uuid.uuid4())
else: else:

View File

@@ -11,7 +11,6 @@ import json
from json_repair import repair_json from json_repair import repair_json
from datetime import datetime from datetime import datetime
from difflib import SequenceMatcher from difflib import SequenceMatcher
import ast
import jieba import jieba
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity 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) await person_info_manager.update_one_field(person_id, "impression", compressed_summary)
compress_short_prompt = f""" compress_short_prompt = f"""
你的名字是{global_config.bot.nickname}{global_config.bot.nickname}的别名是{alias_str} 你的名字是{global_config.bot.nickname}{global_config.bot.nickname}的别名是{alias_str}
请不要混淆你自己和{global_config.bot.nickname}{person_name} 请不要混淆你自己和{global_config.bot.nickname}{person_name}
@@ -447,19 +443,15 @@ class RelationshipManager:
3.{person_name}的关键信息 3.{person_name}的关键信息
请输出一段平文本,以陈诉自白的语气,输出你对{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") # current_time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S")
# compressed_short_summary = f"截至{current_time},你对{person_name}的了解:{compressed_short_summary}" # 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) await person_info_manager.update_one_field(person_id, "short_impression", compressed_short_summary)
forgotten_points = [] forgotten_points = []
# 这句代码的作用是:将更新后的 forgotten_points遗忘的记忆点列表序列化为 JSON 字符串后,写回到数据库中的 forgotten_points 字段 # 这句代码的作用是:将更新后的 forgotten_points遗忘的记忆点列表序列化为 JSON 字符串后,写回到数据库中的 forgotten_points 字段