ruff reformatted
This commit is contained in:
@@ -8,7 +8,8 @@ import asyncio
|
||||
import numpy as np
|
||||
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
|
||||
matplotlib.use("Agg")
|
||||
import matplotlib.pyplot as plt
|
||||
from pathlib import Path
|
||||
import pandas as pd
|
||||
@@ -30,38 +31,39 @@ PersonInfoManager 类方法功能摘要:
|
||||
logger = get_module_logger("person_info")
|
||||
|
||||
person_info_default = {
|
||||
"person_id" : None,
|
||||
"platform" : None,
|
||||
"user_id" : None,
|
||||
"nickname" : None,
|
||||
"person_id": None,
|
||||
"platform": None,
|
||||
"user_id": None,
|
||||
"nickname": None,
|
||||
# "age" : 0,
|
||||
"relationship_value" : 0,
|
||||
"relationship_value": 0,
|
||||
# "saved" : True,
|
||||
# "impression" : None,
|
||||
# "gender" : Unkown,
|
||||
"konw_time" : 0,
|
||||
"konw_time": 0,
|
||||
"msg_interval": 3000,
|
||||
"msg_interval_list": []
|
||||
"msg_interval_list": [],
|
||||
} # 个人信息的各项与默认值在此定义,以下处理会自动创建/补全每一项
|
||||
|
||||
|
||||
class PersonInfoManager:
|
||||
def __init__(self):
|
||||
if "person_info" not in db.list_collection_names():
|
||||
db.create_collection("person_info")
|
||||
db.person_info.create_index("person_id", unique=True)
|
||||
|
||||
def get_person_id(self, platform:str, user_id:int):
|
||||
def get_person_id(self, platform: str, user_id: int):
|
||||
"""获取唯一id"""
|
||||
components = [platform, str(user_id)]
|
||||
key = "_".join(components)
|
||||
return hashlib.md5(key.encode()).hexdigest()
|
||||
|
||||
async def create_person_info(self, person_id:str, data:dict = None):
|
||||
async def create_person_info(self, person_id: str, data: dict = None):
|
||||
"""创建一个项"""
|
||||
if not person_id:
|
||||
logger.debug("创建失败,personid不存在")
|
||||
return
|
||||
|
||||
|
||||
_person_info_default = copy.deepcopy(person_info_default)
|
||||
_person_info_default["person_id"] = person_id
|
||||
|
||||
@@ -72,19 +74,16 @@ class PersonInfoManager:
|
||||
|
||||
db.person_info.insert_one(_person_info_default)
|
||||
|
||||
async def update_one_field(self, person_id:str, field_name:str, value, Data:dict = None):
|
||||
async def update_one_field(self, person_id: str, field_name: str, value, Data: dict = None):
|
||||
"""更新某一个字段,会补全"""
|
||||
if field_name not in person_info_default.keys():
|
||||
logger.debug(f"更新'{field_name}'失败,未定义的字段")
|
||||
return
|
||||
|
||||
|
||||
document = db.person_info.find_one({"person_id": person_id})
|
||||
|
||||
if document:
|
||||
db.person_info.update_one(
|
||||
{"person_id": person_id},
|
||||
{"$set": {field_name: value}}
|
||||
)
|
||||
db.person_info.update_one({"person_id": person_id}, {"$set": {field_name: value}})
|
||||
else:
|
||||
Data[field_name] = value
|
||||
logger.debug(f"更新时{person_id}不存在,已新建")
|
||||
@@ -107,23 +106,20 @@ class PersonInfoManager:
|
||||
if not person_id:
|
||||
logger.debug("get_value获取失败:person_id不能为空")
|
||||
return None
|
||||
|
||||
|
||||
if field_name not in person_info_default:
|
||||
logger.debug(f"get_value获取失败:字段'{field_name}'未定义")
|
||||
return None
|
||||
|
||||
document = db.person_info.find_one(
|
||||
{"person_id": person_id},
|
||||
{field_name: 1}
|
||||
)
|
||||
|
||||
|
||||
document = db.person_info.find_one({"person_id": person_id}, {field_name: 1})
|
||||
|
||||
if document and field_name in document:
|
||||
return document[field_name]
|
||||
else:
|
||||
default_value = copy.deepcopy(person_info_default[field_name])
|
||||
logger.debug(f"获取{person_id}的{field_name}失败,已返回默认值{default_value}")
|
||||
return default_value
|
||||
|
||||
|
||||
async def get_values(self, person_id: str, field_names: list) -> dict:
|
||||
"""获取指定person_id文档的多个字段值,若不存在该字段,则返回该字段的全局默认值"""
|
||||
if not person_id:
|
||||
@@ -139,62 +135,57 @@ class PersonInfoManager:
|
||||
# 构建查询投影(所有字段都有效才会执行到这里)
|
||||
projection = {field: 1 for field in field_names}
|
||||
|
||||
document = db.person_info.find_one(
|
||||
{"person_id": person_id},
|
||||
projection
|
||||
)
|
||||
document = db.person_info.find_one({"person_id": person_id}, projection)
|
||||
|
||||
result = {}
|
||||
for field in field_names:
|
||||
result[field] = copy.deepcopy(
|
||||
document.get(field, person_info_default[field])
|
||||
if document else person_info_default[field]
|
||||
document.get(field, person_info_default[field]) if document else person_info_default[field]
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
async def del_all_undefined_field(self):
|
||||
"""删除所有项里的未定义字段"""
|
||||
# 获取所有已定义的字段名
|
||||
defined_fields = set(person_info_default.keys())
|
||||
|
||||
|
||||
try:
|
||||
# 遍历集合中的所有文档
|
||||
for document in db.person_info.find({}):
|
||||
# 找出文档中未定义的字段
|
||||
undefined_fields = set(document.keys()) - defined_fields - {'_id'}
|
||||
|
||||
undefined_fields = set(document.keys()) - defined_fields - {"_id"}
|
||||
|
||||
if undefined_fields:
|
||||
# 构建更新操作,使用$unset删除未定义字段
|
||||
update_result = db.person_info.update_one(
|
||||
{'_id': document['_id']},
|
||||
{'$unset': {field: 1 for field in undefined_fields}}
|
||||
{"_id": document["_id"]}, {"$unset": {field: 1 for field in undefined_fields}}
|
||||
)
|
||||
|
||||
|
||||
if update_result.modified_count > 0:
|
||||
logger.debug(f"已清理文档 {document['_id']} 的未定义字段: {undefined_fields}")
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"清理未定义字段时出错: {e}")
|
||||
return
|
||||
|
||||
|
||||
async def get_specific_value_list(
|
||||
self,
|
||||
field_name: str,
|
||||
way: Callable[[Any], bool], # 接受任意类型值
|
||||
) ->Dict[str, Any]:
|
||||
self,
|
||||
field_name: str,
|
||||
way: Callable[[Any], bool], # 接受任意类型值
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
获取满足条件的字段值字典
|
||||
|
||||
|
||||
Args:
|
||||
field_name: 目标字段名
|
||||
way: 判断函数 (value: Any) -> bool
|
||||
|
||||
|
||||
Returns:
|
||||
{person_id: value} | {}
|
||||
|
||||
|
||||
Example:
|
||||
# 查找所有nickname包含"admin"的用户
|
||||
result = manager.specific_value_list(
|
||||
@@ -208,10 +199,7 @@ class PersonInfoManager:
|
||||
|
||||
try:
|
||||
result = {}
|
||||
for doc in db.person_info.find(
|
||||
{field_name: {"$exists": True}},
|
||||
{"person_id": 1, field_name: 1, "_id": 0}
|
||||
):
|
||||
for doc in db.person_info.find({field_name: {"$exists": True}}, {"person_id": 1, field_name: 1, "_id": 0}):
|
||||
try:
|
||||
value = doc[field_name]
|
||||
if way(value):
|
||||
@@ -225,11 +213,11 @@ class PersonInfoManager:
|
||||
except Exception as e:
|
||||
logger.error(f"数据库查询失败: {str(e)}", exc_info=True)
|
||||
return {}
|
||||
|
||||
|
||||
async def personal_habit_deduction(self):
|
||||
"""启动个人信息推断,每天根据一定条件推断一次"""
|
||||
try:
|
||||
while(1):
|
||||
while 1:
|
||||
await asyncio.sleep(60)
|
||||
current_time = datetime.datetime.now()
|
||||
logger.info(f"个人信息推断启动: {current_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
@@ -237,8 +225,7 @@ class PersonInfoManager:
|
||||
# "msg_interval"推断
|
||||
msg_interval_map = False
|
||||
msg_interval_lists = await self.get_specific_value_list(
|
||||
"msg_interval_list",
|
||||
lambda x: isinstance(x, list) and len(x) >= 100
|
||||
"msg_interval_list", lambda x: isinstance(x, list) and len(x) >= 100
|
||||
)
|
||||
for person_id, msg_interval_list_ in msg_interval_lists.items():
|
||||
try:
|
||||
@@ -258,23 +245,23 @@ class PersonInfoManager:
|
||||
log_dir.mkdir(parents=True, exist_ok=True)
|
||||
plt.figure(figsize=(10, 6))
|
||||
time_series = pd.Series(time_interval)
|
||||
plt.hist(time_series, bins=50, density=True, alpha=0.4, color='pink', label='Histogram')
|
||||
time_series.plot(kind='kde', color='mediumpurple', linewidth=1, label='Density')
|
||||
plt.hist(time_series, bins=50, density=True, alpha=0.4, color="pink", label="Histogram")
|
||||
time_series.plot(kind="kde", color="mediumpurple", linewidth=1, label="Density")
|
||||
plt.grid(True, alpha=0.2)
|
||||
plt.xlim(0, 8000)
|
||||
plt.title(f"Message Interval Distribution (User: {person_id[:8]}...)")
|
||||
plt.xlabel("Interval (ms)")
|
||||
plt.ylabel("Density")
|
||||
plt.legend(framealpha=0.9, facecolor='white')
|
||||
plt.legend(framealpha=0.9, facecolor="white")
|
||||
img_path = log_dir / f"interval_distribution_{person_id[:8]}.png"
|
||||
plt.savefig(img_path)
|
||||
plt.close()
|
||||
# 画图
|
||||
|
||||
|
||||
q25, q75 = np.percentile(time_interval, [25, 75])
|
||||
iqr = q75 - q25
|
||||
filtered = [x for x in time_interval if (q25 - 1.5*iqr) <= x <= (q75 + 1.5*iqr)]
|
||||
|
||||
filtered = [x for x in time_interval if (q25 - 1.5 * iqr) <= x <= (q75 + 1.5 * iqr)]
|
||||
|
||||
msg_interval = int(round(np.percentile(filtered, 80)))
|
||||
await self.update_one_field(person_id, "msg_interval", msg_interval)
|
||||
logger.debug(f"用户{person_id}的msg_interval已经被更新为{msg_interval}")
|
||||
|
||||
@@ -12,6 +12,7 @@ relationship_config = LogConfig(
|
||||
)
|
||||
logger = get_module_logger("rel_manager", config=relationship_config)
|
||||
|
||||
|
||||
class RelationshipManager:
|
||||
def __init__(self):
|
||||
self.positive_feedback_value = 0 # 正反馈系统
|
||||
@@ -22,6 +23,7 @@ class RelationshipManager:
|
||||
def mood_manager(self):
|
||||
if self._mood_manager is None:
|
||||
from ..moods.moods import MoodManager # 延迟导入
|
||||
|
||||
self._mood_manager = MoodManager.get_instance()
|
||||
return self._mood_manager
|
||||
|
||||
@@ -51,27 +53,27 @@ class RelationshipManager:
|
||||
self.positive_feedback_value -= 1
|
||||
elif self.positive_feedback_value > 0:
|
||||
self.positive_feedback_value = 0
|
||||
|
||||
|
||||
if abs(self.positive_feedback_value) > 1:
|
||||
logger.info(f"触发mood变更增益,当前增益系数:{self.gain_coefficient[abs(self.positive_feedback_value)]}")
|
||||
|
||||
def mood_feedback(self, value):
|
||||
"""情绪反馈"""
|
||||
mood_manager = self.mood_manager
|
||||
mood_gain = (mood_manager.get_current_mood().valence) ** 2 \
|
||||
* math.copysign(1, value * mood_manager.get_current_mood().valence)
|
||||
mood_gain = (mood_manager.get_current_mood().valence) ** 2 * math.copysign(
|
||||
1, value * mood_manager.get_current_mood().valence
|
||||
)
|
||||
value += value * mood_gain
|
||||
logger.info(f"当前relationship增益系数:{mood_gain:.3f}")
|
||||
return value
|
||||
|
||||
|
||||
def feedback_to_mood(self, mood_value):
|
||||
"""对情绪的反馈"""
|
||||
coefficient = self.gain_coefficient[abs(self.positive_feedback_value)]
|
||||
if (mood_value > 0 and self.positive_feedback_value > 0
|
||||
or mood_value < 0 and self.positive_feedback_value < 0):
|
||||
return mood_value*coefficient
|
||||
if mood_value > 0 and self.positive_feedback_value > 0 or mood_value < 0 and self.positive_feedback_value < 0:
|
||||
return mood_value * coefficient
|
||||
else:
|
||||
return mood_value/coefficient
|
||||
return mood_value / coefficient
|
||||
|
||||
async def calculate_update_relationship_value(self, chat_stream: ChatStream, label: str, stance: str) -> None:
|
||||
"""计算并变更关系值
|
||||
@@ -88,7 +90,7 @@ class RelationshipManager:
|
||||
"中立": 1,
|
||||
"反对": 2,
|
||||
}
|
||||
|
||||
|
||||
valuedict = {
|
||||
"开心": 1.5,
|
||||
"愤怒": -2.0,
|
||||
@@ -103,10 +105,10 @@ class RelationshipManager:
|
||||
|
||||
person_id = person_info_manager.get_person_id(chat_stream.user_info.platform, chat_stream.user_info.user_id)
|
||||
data = {
|
||||
"platform" : chat_stream.user_info.platform,
|
||||
"user_id" : chat_stream.user_info.user_id,
|
||||
"nickname" : chat_stream.user_info.user_nickname,
|
||||
"konw_time" : int(time.time())
|
||||
"platform": chat_stream.user_info.platform,
|
||||
"user_id": chat_stream.user_info.user_id,
|
||||
"nickname": chat_stream.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)
|
||||
@@ -200,4 +202,5 @@ class RelationshipManager:
|
||||
logger.warning(f"[关系管理] {person_id}值转换失败(原始值:{value}),已重置为0")
|
||||
return 0.0
|
||||
|
||||
|
||||
relationship_manager = RelationshipManager()
|
||||
|
||||
Reference in New Issue
Block a user