feat:新增用户侧写功能

This commit is contained in:
SengokuCola
2025-06-03 17:08:12 +08:00
parent 178feb3c5a
commit e888636ea0
6 changed files with 263 additions and 110 deletions

View File

@@ -1,26 +1,29 @@
from src.common.logger_manager import get_logger
from src.chat.message_receive.chat_stream import ChatStream
import math
from bson.decimal128 import Decimal128
from src.person_info.person_info import person_info_manager
import time
import random
from maim_message import UserInfo
from src.llm_models.utils_model import LLMRequest
from src.config.config import global_config
from src.chat.utils.chat_message_builder import get_raw_msg_by_timestamp_with_chat_users
from src.chat.utils.chat_message_builder import build_readable_messages
from src.manager.mood_manager import mood_manager
# import re
# import traceback
logger = get_logger("relation")
class RelationshipManager:
def __init__(self):
self.positive_feedback_value = 0 # 正反馈系统
self.gain_coefficient = [1.0, 1.0, 1.1, 1.2, 1.4, 1.7, 1.9, 2.0]
self._mood_manager = None
self.relationship_llm = LLMRequest(
model=global_config.model.normal_chat_1,
max_tokens=1000,
request_type="relationship", # 用于动作规划
)
@property
def mood_manager(self):
@@ -112,91 +115,6 @@ class RelationshipManager:
person_id=person_id, user_nickname=user_nickname, user_cardname=user_cardname, user_avatar=user_avatar
)
async def calculate_update_relationship_value(self, user_info: UserInfo, platform: str, label: str, stance: str):
"""计算并变更关系值
新的关系值变更计算方式:
将关系值限定在-1000到1000
对于关系值的变更,期望:
1.向两端逼近时会逐渐减缓
2.关系越差,改善越难,关系越好,恶化越容易
3.人维护关系的精力往往有限,所以当高关系值用户越多,对于中高关系值用户增长越慢
4.连续正面或负面情感会正反馈
返回:
用户昵称,变更值,变更后关系等级
"""
stancedict = {
"支持": 0,
"中立": 1,
"反对": 2,
}
valuedict = {
"开心": 1.5,
"愤怒": -2.0,
"悲伤": -0.5,
"惊讶": 0.6,
"害羞": 2.0,
"平静": 0.3,
"恐惧": -1.5,
"厌恶": -1.0,
"困惑": 0.5,
}
person_id = person_info_manager.get_person_id(platform, user_info.user_id)
data = {
"platform": platform,
"user_id": user_info.user_id,
"nickname": user_info.user_nickname,
"konw_time": int(time.time()),
}
old_value = await person_info_manager.get_value(person_id, "relationship_value")
old_value = self.ensure_float(old_value, person_id)
if old_value > 1000:
old_value = 1000
elif old_value < -1000:
old_value = -1000
value = valuedict[label]
if old_value >= 0:
if valuedict[label] >= 0 and stancedict[stance] != 2:
value = value * math.cos(math.pi * old_value / 2000)
if old_value > 500:
rdict = await person_info_manager.get_specific_value_list("relationship_value", lambda x: x > 700)
high_value_count = len(rdict)
if old_value > 700:
value *= 3 / (high_value_count + 2) # 排除自己
else:
value *= 3 / (high_value_count + 3)
elif valuedict[label] < 0 and stancedict[stance] != 0:
value = value * math.exp(old_value / 2000)
else:
value = 0
elif old_value < 0:
if valuedict[label] >= 0 and stancedict[stance] != 2:
value = value * math.exp(old_value / 2000)
elif valuedict[label] < 0 and stancedict[stance] != 0:
value = value * math.cos(math.pi * old_value / 2000)
else:
value = 0
self.positive_feedback_sys(label, stance)
value = self.mood_feedback(value)
level_num = self.calculate_level_num(old_value + value)
relationship_level = ["厌恶", "冷漠", "一般", "友好", "喜欢", "暧昧"]
logger.info(
f"用户: {user_info.user_nickname}"
f"当前关系: {relationship_level[level_num]}, "
f"关系值: {old_value:.2f}, "
f"当前立场情感: {stance}-{label}, "
f"变更: {value:+.5f}"
)
await person_info_manager.update_one_field(person_id, "relationship_value", old_value + value, data)
async def calculate_update_relationship_value_with_reason(
self, chat_stream: ChatStream, label: str, stance: str, reason: str
) -> tuple:
@@ -337,6 +255,14 @@ class RelationshipManager:
relation_prompt = f"{relation_value_prompt}ta在{platform}上的昵称是{nickname_str}\n"
else:
relation_prompt = ""
person_name_reason = await person_info_manager.get_value(person_id, "person_name_reason")
if person_name_reason:
relation_prompt += f"ta的昵称{person_name}的由来是:{person_name_reason}\n"
person_impression = await person_info_manager.get_value(person_id, "person_impression")
if person_impression:
relation_prompt += f"ta的印象是{person_impression}\n"
return relation_prompt
@@ -358,17 +284,95 @@ class RelationshipManager:
else:
level_num = 5 if relationship_value > 1000 else 0
return level_num
async def update_person_impression(self, person_id, chat_id, reason, timestamp):
"""更新用户印象
Args:
person_id: 用户ID
chat_id: 聊天ID
reason: 更新原因
timestamp: 时间戳
"""
# 获取现有印象和用户信息
person_name = await person_info_manager.get_value(person_id, "person_name")
nickname = await person_info_manager.get_value(person_id, "nickname")
old_impression = await person_info_manager.get_value(person_id, "person_impression")
user_id = await person_info_manager.get_value(person_id, "user_id")
logger.debug(f"更新印象的person_id: {person_id}, chat_id: {chat_id}, reason: {reason}, timestamp: {timestamp}, user_id: {user_id}")
@staticmethod
def ensure_float(value, person_id):
"""确保返回浮点数转换失败返回0.0"""
if isinstance(value, float):
return value
try:
return float(value.to_decimal() if isinstance(value, Decimal128) else value)
except (ValueError, TypeError, AttributeError):
logger.warning(f"[关系管理] {person_id}值转换失败(原始值:{value}已重置为0")
return 0.0
# 获取时间戳前后的消息
messages_before = get_raw_msg_by_timestamp_with_chat_users(
chat_id=chat_id,
timestamp_start=timestamp - 3600, # 前1小时
timestamp_end=timestamp,
person_ids=[user_id],
limit=30,
limit_mode="latest"
)
messages_after = get_raw_msg_by_timestamp_with_chat_users(
chat_id=chat_id,
timestamp_start=timestamp,
timestamp_end=timestamp + 3600, # 后1小时
person_ids=[user_id],
limit=30,
limit_mode="earliest"
)
# 合并消息并按时间排序
user_messages = messages_before + messages_after
user_messages.sort(key=lambda x: x["time"])
# print(f"user_messages: {user_messages}")
# 构建可读消息
readable_messages = await build_readable_messages(
messages=user_messages,
replace_bot_name=True,
timestamp_mode="relative",
truncate=False
)
# 使用LLM总结印象
prompt = f"""基于以下信息,总结对{person_name}(昵称:{nickname})的印象:
原因:{reason}
历史印象:{old_impression if old_impression else ''}
最近发言:
{readable_messages}
请用简洁的语言总结对这个人的印象不超过200字。"""
new_impression, _ = await self.relationship_llm.generate_response_async(prompt=prompt)
logger.debug(f"新印象prompt{prompt}")
logger.info(f"新印象:{new_impression}")
# 合并新旧印象
if old_impression:
merge_prompt = f"""请将以下两段印象合并,形成一段连贯的描述:
旧印象:{old_impression}
新印象:{new_impression}
请用简洁的语言合并这两段印象不超过200字。"""
final_impression, _ = await self.relationship_llm.generate_response_async(prompt=merge_prompt)
logger.debug(f"合并印象prompt{merge_prompt}")
logger.info(f"合并印象:{final_impression}")
else:
final_impression = new_impression
# 更新到数据库
await person_info_manager.update_one_field(person_id, "person_impression", final_impression)
return final_impression
relationship_manager = RelationshipManager()