ruff reformatted

This commit is contained in:
春河晴
2025-04-08 15:31:13 +09:00
parent 0d7068acab
commit 7840a6080d
40 changed files with 1227 additions and 1336 deletions

View File

@@ -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}")

View File

@@ -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()