feat(person-info): 增强人物关系信息构建功能
重构关系信息构建逻辑,从数据库查询更多维度数据生成详细关系描述: - 增加认识时间、交流频率、态度评分等基本信息 - 整合UserRelationships表的额外关系数据 - 添加态度和关系分数的描述性文字转换方法 - 优化特征点选择策略,按权重和时效性综合排序 - 提供更结构化的关系信息输出格式
This commit is contained in:
@@ -31,7 +31,6 @@ from src.chat.express.expression_selector import expression_selector
|
|||||||
from src.chat.memory_system.memory_activator import MemoryActivator
|
from src.chat.memory_system.memory_activator import MemoryActivator
|
||||||
from src.chat.memory_system.vector_instant_memory import VectorInstantMemoryV2
|
from src.chat.memory_system.vector_instant_memory import VectorInstantMemoryV2
|
||||||
from src.mood.mood_manager import mood_manager
|
from src.mood.mood_manager import mood_manager
|
||||||
from src.person_info.relationship_fetcher import relationship_fetcher_manager
|
|
||||||
from src.person_info.person_info import get_person_info_manager
|
from src.person_info.person_info import get_person_info_manager
|
||||||
from src.plugin_system.base.component_types import ActionInfo, EventType
|
from src.plugin_system.base.component_types import ActionInfo, EventType
|
||||||
from src.plugin_system.apis import llm_api
|
from src.plugin_system.apis import llm_api
|
||||||
@@ -1478,8 +1477,6 @@ class DefaultReplyer:
|
|||||||
if not global_config.relationship.enable_relationship:
|
if not global_config.relationship.enable_relationship:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
relationship_fetcher = relationship_fetcher_manager.get_fetcher(self.chat_stream.stream_id)
|
|
||||||
|
|
||||||
# 获取用户ID
|
# 获取用户ID
|
||||||
person_info_manager = get_person_info_manager()
|
person_info_manager = get_person_info_manager()
|
||||||
person_id = person_info_manager.get_person_id_by_person_name(sender)
|
person_id = person_info_manager.get_person_id_by_person_name(sender)
|
||||||
@@ -1487,7 +1484,48 @@ class DefaultReplyer:
|
|||||||
logger.warning(f"未找到用户 {sender} 的ID,跳过信息提取")
|
logger.warning(f"未找到用户 {sender} 的ID,跳过信息提取")
|
||||||
return f"你完全不认识{sender},不理解ta的相关信息。"
|
return f"你完全不认识{sender},不理解ta的相关信息。"
|
||||||
|
|
||||||
return await relationship_fetcher.build_relation_info(person_id, points_num=5)
|
# 使用AFC关系追踪器获取关系信息
|
||||||
|
try:
|
||||||
|
from src.chat.affinity_flow.relationship_integration import get_relationship_tracker
|
||||||
|
|
||||||
|
relationship_tracker = get_relationship_tracker()
|
||||||
|
if relationship_tracker:
|
||||||
|
# 获取用户信息以获取真实的user_id
|
||||||
|
user_info = await person_info_manager.get_values(person_id, ["user_id", "platform"])
|
||||||
|
user_id = user_info.get("user_id", "unknown")
|
||||||
|
|
||||||
|
# 从数据库获取关系数据
|
||||||
|
relationship_data = relationship_tracker._get_user_relationship_from_db(user_id)
|
||||||
|
if relationship_data:
|
||||||
|
relationship_text = relationship_data.get("relationship_text", "")
|
||||||
|
relationship_score = relationship_data.get("relationship_score", 0.3)
|
||||||
|
|
||||||
|
# 构建丰富的关系信息描述
|
||||||
|
if relationship_text:
|
||||||
|
# 转换关系分数为描述性文本
|
||||||
|
if relationship_score >= 0.8:
|
||||||
|
relationship_level = "非常亲密的朋友"
|
||||||
|
elif relationship_score >= 0.6:
|
||||||
|
relationship_level = "好朋友"
|
||||||
|
elif relationship_score >= 0.4:
|
||||||
|
relationship_level = "普通朋友"
|
||||||
|
elif relationship_score >= 0.2:
|
||||||
|
relationship_level = "认识的人"
|
||||||
|
else:
|
||||||
|
relationship_level = "陌生人"
|
||||||
|
|
||||||
|
return f"你与{sender}的关系:{relationship_level}(关系分:{relationship_score:.2f}/1.0)。{relationship_text}"
|
||||||
|
else:
|
||||||
|
return f"你与{sender}是初次见面,关系分:{relationship_score:.2f}/1.0。"
|
||||||
|
else:
|
||||||
|
return f"你完全不认识{sender},这是第一次互动。"
|
||||||
|
else:
|
||||||
|
logger.warning("AFC关系追踪器未初始化,使用默认关系信息")
|
||||||
|
return f"你与{sender}是普通朋友关系。"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"获取AFC关系信息失败: {e}")
|
||||||
|
return f"你与{sender}是普通朋友关系。"
|
||||||
|
|
||||||
|
|
||||||
def weighted_sample_no_replacement(items, weights, k) -> list:
|
def weighted_sample_no_replacement(items, weights, k) -> list:
|
||||||
|
|||||||
@@ -94,78 +94,133 @@ class RelationshipFetcher:
|
|||||||
if not self.info_fetched_cache[person_id]:
|
if not self.info_fetched_cache[person_id]:
|
||||||
del self.info_fetched_cache[person_id]
|
del self.info_fetched_cache[person_id]
|
||||||
|
|
||||||
async def build_relation_info(self, person_id, points_num=3):
|
async def build_relation_info(self, person_id, points_num=5):
|
||||||
|
"""构建详细的人物关系信息,包含从数据库中查询的丰富关系描述"""
|
||||||
# 清理过期的信息缓存
|
# 清理过期的信息缓存
|
||||||
self._cleanup_expired_cache()
|
self._cleanup_expired_cache()
|
||||||
|
|
||||||
person_info_manager = get_person_info_manager()
|
person_info_manager = get_person_info_manager()
|
||||||
person_name = await person_info_manager.get_value(person_id, "person_name")
|
person_name = await person_info_manager.get_value(person_id, "person_name")
|
||||||
short_impression = await person_info_manager.get_value(person_id, "short_impression")
|
short_impression = await person_info_manager.get_value(person_id, "short_impression")
|
||||||
|
full_impression = await person_info_manager.get_value(person_id, "impression")
|
||||||
|
attitude = await person_info_manager.get_value(person_id, "attitude") or 50
|
||||||
|
|
||||||
nickname_str = await person_info_manager.get_value(person_id, "nickname")
|
nickname_str = await person_info_manager.get_value(person_id, "nickname")
|
||||||
platform = await person_info_manager.get_value(person_id, "platform")
|
platform = await person_info_manager.get_value(person_id, "platform")
|
||||||
|
know_times = await person_info_manager.get_value(person_id, "know_times") or 0
|
||||||
|
know_since = await person_info_manager.get_value(person_id, "know_since")
|
||||||
|
last_know = await person_info_manager.get_value(person_id, "last_know")
|
||||||
|
|
||||||
if person_name == nickname_str and not short_impression:
|
# 如果用户没有基本信息,返回默认描述
|
||||||
return ""
|
if person_name == nickname_str and not short_impression and not full_impression:
|
||||||
|
return f"你完全不认识{person_name},这是你们第一次交流。"
|
||||||
|
|
||||||
|
# 获取用户特征点
|
||||||
current_points = await person_info_manager.get_value(person_id, "points") or []
|
current_points = await person_info_manager.get_value(person_id, "points") or []
|
||||||
|
forgotten_points = await person_info_manager.get_value(person_id, "forgotten_points") or []
|
||||||
|
|
||||||
# 按时间排序forgotten_points
|
# 按时间排序并选择最有代表性的特征点
|
||||||
current_points.sort(key=lambda x: x[2])
|
all_points = current_points + forgotten_points
|
||||||
# 按权重加权随机抽取最多3个不重复的points,point[1]的值在1-10之间,权重越高被抽到概率越大
|
if all_points:
|
||||||
if len(current_points) > points_num:
|
# 按权重和时效性综合排序
|
||||||
# point[1] 取值范围1-10,直接作为权重
|
all_points.sort(key=lambda x: (float(x[1]) if len(x) > 1 else 0, float(x[2]) if len(x) > 2 else 0), reverse=True)
|
||||||
weights = [max(1, min(10, int(point[1]))) for point in current_points]
|
selected_points = all_points[:points_num]
|
||||||
# 使用加权采样不放回,保证不重复
|
points_text = "\n".join([f"- {point[0]}({point[2]})" for point in selected_points if len(point) > 2])
|
||||||
indices = list(range(len(current_points)))
|
|
||||||
points = []
|
|
||||||
for _ in range(points_num):
|
|
||||||
if not indices:
|
|
||||||
break
|
|
||||||
sub_weights = [weights[i] for i in indices]
|
|
||||||
chosen_idx = random.choices(indices, weights=sub_weights, k=1)[0]
|
|
||||||
points.append(current_points[chosen_idx])
|
|
||||||
indices.remove(chosen_idx)
|
|
||||||
else:
|
else:
|
||||||
points = current_points
|
points_text = ""
|
||||||
|
|
||||||
# 构建points文本
|
# 构建详细的关系描述
|
||||||
points_text = "\n".join([f"{point[2]}:{point[0]}" for point in points])
|
relation_parts = []
|
||||||
|
|
||||||
nickname_str = ""
|
# 1. 基本信息
|
||||||
if person_name != nickname_str:
|
if nickname_str and person_name != nickname_str:
|
||||||
nickname_str = f"(ta在{platform}上的昵称是{nickname_str})"
|
relation_parts.append(f"用户{person_name}在{platform}平台的昵称是{nickname_str}")
|
||||||
|
|
||||||
relation_info = ""
|
# 2. 认识时间和频率
|
||||||
|
if know_since:
|
||||||
|
from datetime import datetime
|
||||||
|
know_time = datetime.fromtimestamp(know_since).strftime('%Y年%m月%d日')
|
||||||
|
relation_parts.append(f"你从{know_time}开始认识{person_name}")
|
||||||
|
|
||||||
|
if know_times > 0:
|
||||||
|
relation_parts.append(f"你们已经交流过{int(know_times)}次")
|
||||||
|
|
||||||
|
if last_know:
|
||||||
|
from datetime import datetime
|
||||||
|
last_time = datetime.fromtimestamp(last_know).strftime('%m月%d日')
|
||||||
|
relation_parts.append(f"最近一次交流是在{last_time}")
|
||||||
|
|
||||||
if short_impression and relation_info:
|
# 3. 态度和印象
|
||||||
if points_text:
|
attitude_desc = self._get_attitude_description(attitude)
|
||||||
relation_info = f"你对{person_name}的印象是{nickname_str}:{short_impression}。具体来说:{relation_info}。你还记得ta最近做的事:{points_text}"
|
relation_parts.append(f"你对{person_name}的态度是{attitude_desc}")
|
||||||
else:
|
|
||||||
relation_info = (
|
if short_impression:
|
||||||
f"你对{person_name}的印象是{nickname_str}:{short_impression}。具体来说:{relation_info}"
|
relation_parts.append(f"你对ta的总体印象:{short_impression}")
|
||||||
)
|
|
||||||
elif short_impression:
|
if full_impression:
|
||||||
if points_text:
|
relation_parts.append(f"更详细的了解:{full_impression}")
|
||||||
relation_info = (
|
|
||||||
f"你对{person_name}的印象是{nickname_str}:{short_impression}。你还记得ta最近做的事:{points_text}"
|
# 4. 特征点和记忆
|
||||||
)
|
if points_text:
|
||||||
else:
|
relation_parts.append(f"你记得关于{person_name}的一些事情:\n{points_text}")
|
||||||
relation_info = f"你对{person_name}的印象是{nickname_str}:{short_impression}"
|
|
||||||
elif relation_info:
|
# 5. 从UserRelationships表获取额外关系信息
|
||||||
if points_text:
|
try:
|
||||||
relation_info = (
|
from src.common.database.sqlalchemy_database_api import db_query
|
||||||
f"你对{person_name}的了解{nickname_str}:{relation_info}。你还记得ta最近做的事:{points_text}"
|
from src.common.database.sqlalchemy_models import UserRelationships
|
||||||
)
|
|
||||||
else:
|
# 查询用户关系数据
|
||||||
relation_info = f"你对{person_name}的了解{nickname_str}:{relation_info}"
|
relationships = await db_query(
|
||||||
elif points_text:
|
UserRelationships,
|
||||||
relation_info = f"你记得{person_name}{nickname_str}最近做的事:{points_text}"
|
filters=[UserRelationships.user_id == str(person_info_manager.get_value_sync(person_id, "user_id"))],
|
||||||
|
limit=1
|
||||||
|
)
|
||||||
|
|
||||||
|
if relationships:
|
||||||
|
rel_data = relationships[0]
|
||||||
|
if rel_data.relationship_text:
|
||||||
|
relation_parts.append(f"关系记录:{rel_data.relationship_text}")
|
||||||
|
if rel_data.relationship_score:
|
||||||
|
score_desc = self._get_relationship_score_description(rel_data.relationship_score)
|
||||||
|
relation_parts.append(f"关系亲密程度:{score_desc}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"查询UserRelationships表失败: {e}")
|
||||||
|
|
||||||
|
# 构建最终的关系信息字符串
|
||||||
|
if relation_parts:
|
||||||
|
relation_info = f"关于{person_name},你知道以下信息:\n" + "\n".join([f"• {part}" for part in relation_parts])
|
||||||
else:
|
else:
|
||||||
relation_info = ""
|
relation_info = f"你对{person_name}了解不多,这是比较初步的交流。"
|
||||||
|
|
||||||
return relation_info
|
return relation_info
|
||||||
|
|
||||||
|
def _get_attitude_description(self, attitude: int) -> str:
|
||||||
|
"""根据态度分数返回描述性文字"""
|
||||||
|
if attitude >= 80:
|
||||||
|
return "非常喜欢和欣赏"
|
||||||
|
elif attitude >= 60:
|
||||||
|
return "比较有好感"
|
||||||
|
elif attitude >= 40:
|
||||||
|
return "中立态度"
|
||||||
|
elif attitude >= 20:
|
||||||
|
return "有些反感"
|
||||||
|
else:
|
||||||
|
return "非常厌恶"
|
||||||
|
|
||||||
|
def _get_relationship_score_description(self, score: float) -> str:
|
||||||
|
"""根据关系分数返回描述性文字"""
|
||||||
|
if score >= 0.8:
|
||||||
|
return "非常亲密的好友"
|
||||||
|
elif score >= 0.6:
|
||||||
|
return "关系不错的朋友"
|
||||||
|
elif score >= 0.4:
|
||||||
|
return "普通熟人"
|
||||||
|
elif score >= 0.2:
|
||||||
|
return "认识但不熟悉"
|
||||||
|
else:
|
||||||
|
return "陌生人"
|
||||||
|
|
||||||
async def _build_fetch_query(self, person_id, target_message, chat_history):
|
async def _build_fetch_query(self, person_id, target_message, chat_history):
|
||||||
nickname_str = ",".join(global_config.bot.alias_names)
|
nickname_str = ",".join(global_config.bot.alias_names)
|
||||||
name_block = f"你的名字是{global_config.bot.nickname},你的昵称有{nickname_str},有人也会用这些昵称称呼你。"
|
name_block = f"你的名字是{global_config.bot.nickname},你的昵称有{nickname_str},有人也会用这些昵称称呼你。"
|
||||||
|
|||||||
Reference in New Issue
Block a user