feat(person_info): 实施基于稳健 ID 的用户信息同步。本次提交重构了用户识别和信息检索系统,使其基于稳定的平台和用户 ID,不再依赖脆弱的姓名解析机制。同时引入了自动后台进程,以保持用户信息的实时更新。主要变更包括:
- 在 `PersonInfoManager` 中新增 `sync_user_info` 方法,根据 `platform` 和 `user_id` 来创建和更新用户记录。 - `ChatManager` 现在会在处理消息时触发该同步作为非阻塞后台任务,确保用户数据(如昵称)保持最新。 - 提示生成逻辑,特别是关系和上下文信息的生成,已重构为使用稳定的 `user_id`,而非从回复消息内容中解析姓名。 - `PromptParameters` 已被扩展,以在整个回复生成流程中传递 `platform` 和 `user_id`。 - 弃用依赖名称到 ID 查找的脆弱方法。
This commit is contained in:
@@ -709,9 +709,17 @@ class Prompt:
|
||||
async def _build_relation_info(self) -> dict[str, Any]:
|
||||
"""构建与对话目标相关的关系信息."""
|
||||
try:
|
||||
# 调用静态方法来执行实际的构建逻辑
|
||||
relation_info = await Prompt.build_relation_info(
|
||||
self.parameters.chat_id, self.parameters.reply_to
|
||||
# [重构] 直接从 PromptParameters 获取稳定的用户身份信息
|
||||
platform = self.parameters.platform
|
||||
user_id = self.parameters.user_id
|
||||
|
||||
if not platform or not user_id:
|
||||
logger.warning("无法从参数中获取platform或user_id,跳过关系信息构建")
|
||||
return {"relation_info_block": ""}
|
||||
|
||||
# 调用新的、基于ID的静态方法
|
||||
relation_info = await Prompt.build_relation_info_by_user_id(
|
||||
self.parameters.chat_id, platform, user_id
|
||||
)
|
||||
return {"relation_info_block": relation_info}
|
||||
except Exception as e:
|
||||
@@ -1063,43 +1071,29 @@ class Prompt:
|
||||
return sender, target
|
||||
|
||||
@staticmethod
|
||||
async def build_relation_info(chat_id: str, reply_to: str) -> str:
|
||||
"""构建关于回复目标用户的关系信息字符串.
|
||||
|
||||
Args:
|
||||
chat_id: 当前聊天的ID。
|
||||
reply_to: 被回复的原始消息字符串。
|
||||
|
||||
Returns:
|
||||
str: 格式化后的关系信息字符串,或在失败时返回空字符串。
|
||||
async def build_relation_info_by_user_id(chat_id: str, platform: str, user_id: str) -> str:
|
||||
"""
|
||||
[新] 根据用户ID构建关系信息字符串。
|
||||
"""
|
||||
from src.person_info.relationship_fetcher import relationship_fetcher_manager
|
||||
|
||||
person_info_manager = get_person_info_manager()
|
||||
person_id = person_info_manager.get_person_id(platform, user_id)
|
||||
|
||||
if not person_id:
|
||||
logger.warning(f"构建关系信息时未找到用户 platform={platform}, user_id={user_id}")
|
||||
return f"你似乎还不认识这位用户(ID: {user_id}),这是你们的第一次互动。"
|
||||
|
||||
relationship_fetcher = relationship_fetcher_manager.get_fetcher(chat_id)
|
||||
|
||||
if not reply_to:
|
||||
return ""
|
||||
# 解析出回复目标的发送者
|
||||
sender, text = Prompt.parse_reply_target(reply_to)
|
||||
if not sender or not text:
|
||||
return ""
|
||||
|
||||
# 根据发送者名称查找其用户ID
|
||||
person_info_manager = get_person_info_manager()
|
||||
person_id = await person_info_manager.get_person_id_by_person_name(sender)
|
||||
if not person_id:
|
||||
logger.warning(f"未找到用户 {sender} 的ID,跳过信息提取")
|
||||
return f"你完全不认识{sender},不理解ta的相关信息。"
|
||||
|
||||
# 使用关系提取器构建用户关系信息和聊天流印象
|
||||
user_relation_info = await relationship_fetcher.build_relation_info(
|
||||
person_id, points_num=5
|
||||
)
|
||||
stream_impression = await relationship_fetcher.build_chat_stream_impression(
|
||||
chat_id
|
||||
|
||||
# 并行构建用户信息和聊天流印象
|
||||
user_relation_info_task = relationship_fetcher.build_relation_info(person_id, points_num=5)
|
||||
stream_impression_task = relationship_fetcher.build_chat_stream_impression(chat_id)
|
||||
|
||||
user_relation_info, stream_impression = await asyncio.gather(
|
||||
user_relation_info_task, stream_impression_task
|
||||
)
|
||||
|
||||
# 组合两部分信息
|
||||
info_parts = []
|
||||
if user_relation_info:
|
||||
info_parts.append(user_relation_info)
|
||||
@@ -1149,6 +1143,7 @@ class Prompt:
|
||||
Returns:
|
||||
str: 构建好的跨群聊上下文字符串。
|
||||
"""
|
||||
logger.info(f"Building cross context with target_user_info: {target_user_info}")
|
||||
if not global_config.cross_context.enable:
|
||||
return ""
|
||||
|
||||
@@ -1167,32 +1162,22 @@ class Prompt:
|
||||
|
||||
return ""
|
||||
|
||||
@staticmethod
|
||||
async def parse_reply_target_id(reply_to: str) -> str:
|
||||
"""从回复目标字符串中解析出原始发送者的用户ID.
|
||||
|
||||
Args:
|
||||
reply_to: 回复目标字符串。
|
||||
|
||||
Returns:
|
||||
str: 找到的用户ID,如果找不到则返回空字符串。
|
||||
"""
|
||||
if not reply_to:
|
||||
return ""
|
||||
|
||||
# 首先,解析出发送者的名称
|
||||
sender, _ = Prompt.parse_reply_target(reply_to)
|
||||
if not sender:
|
||||
return ""
|
||||
|
||||
# 然后,通过名称查询用户ID
|
||||
person_info_manager = get_person_info_manager()
|
||||
person_id = await person_info_manager.get_person_id_by_person_name(sender)
|
||||
if person_id:
|
||||
user_id = await person_info_manager.get_value(person_id, "user_id")
|
||||
return str(user_id) if user_id else ""
|
||||
|
||||
return ""
|
||||
# [废弃] 该函数完全依赖于不稳定的名称解析,应被移除
|
||||
# @staticmethod
|
||||
# async def parse_reply_target_id(reply_to: str) -> str:
|
||||
# """从回复目标字符串中解析出原始发送者的用户ID."""
|
||||
# if not reply_to:
|
||||
# return ""
|
||||
# sender, _ = Prompt.parse_reply_target(reply_to)
|
||||
# if not sender:
|
||||
# return ""
|
||||
# person_info_manager = get_person_info_manager()
|
||||
# # [脆弱点] 使用了不稳健的按名称查询
|
||||
# person_id = await person_info_manager.get_person_id_by_name_robust(sender)
|
||||
# if person_id:
|
||||
# user_id = await person_info_manager.get_value(person_id, "user_id")
|
||||
# return str(user_id) if user_id else ""
|
||||
# return ""
|
||||
|
||||
|
||||
# 工厂函数
|
||||
|
||||
Reference in New Issue
Block a user