refactor(scoring): 重构评分系统使用统一API替代插件内部实现
将原有的兴趣度评分系统重构为使用统一的评分API,移除了插件内部实现并更新了所有相关引用。主要变更包括: - 替换 chatter_interest_scoring_system 为 scoring_api - 移除 interest_scoring.py 文件,统一使用 src/plugin_system/apis/scoring_api - 更新关系追踪器以使用统一API,保持向后兼容性 - 简化了多个模块中的关系分获取逻辑
This commit is contained in:
113
src/plugin_system/apis/scoring_api.py
Normal file
113
src/plugin_system/apis/scoring_api.py
Normal file
@@ -0,0 +1,113 @@
|
||||
"""
|
||||
统一评分系统API
|
||||
提供系统级的关系分和兴趣管理服务,供所有插件和主项目组件使用
|
||||
"""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.plugin_system.services.interest_service import interest_service
|
||||
from src.plugin_system.services.relationship_service import relationship_service
|
||||
|
||||
logger = get_logger("scoring_api")
|
||||
|
||||
|
||||
class ScoringAPI:
|
||||
"""
|
||||
统一评分系统API - 系统级服务
|
||||
|
||||
提供关系分和兴趣管理的统一接口,替代原有的插件依赖方式。
|
||||
所有插件和主项目组件都应该通过此API访问评分功能。
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
async def get_user_relationship_score(user_id: str) -> float:
|
||||
"""
|
||||
获取用户关系分
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
|
||||
Returns:
|
||||
关系分 (0.0 - 1.0)
|
||||
"""
|
||||
return await relationship_service.get_user_relationship_score(user_id)
|
||||
|
||||
@staticmethod
|
||||
async def get_user_relationship_data(user_id: str) -> dict:
|
||||
"""
|
||||
获取用户完整关系数据
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
|
||||
Returns:
|
||||
包含关系分、关系文本等的字典
|
||||
"""
|
||||
return await relationship_service.get_user_relationship_data(user_id)
|
||||
|
||||
@staticmethod
|
||||
async def update_user_relationship(user_id: str, relationship_score: float, relationship_text: str = None, user_name: str = None):
|
||||
"""
|
||||
更新用户关系数据
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
relationship_score: 关系分 (0.0 - 1.0)
|
||||
relationship_text: 关系描述文本
|
||||
user_name: 用户名称
|
||||
"""
|
||||
await relationship_service.update_user_relationship(user_id, relationship_score, relationship_text, user_name)
|
||||
|
||||
@staticmethod
|
||||
async def initialize_smart_interests(personality_description: str, personality_id: str = "default"):
|
||||
"""
|
||||
初始化智能兴趣系统
|
||||
|
||||
Args:
|
||||
personality_description: 机器人性格描述
|
||||
personality_id: 性格ID
|
||||
"""
|
||||
await interest_service.initialize_smart_interests(personality_description, personality_id)
|
||||
|
||||
@staticmethod
|
||||
async def calculate_interest_match(content: str, keywords: list[str] = None):
|
||||
"""
|
||||
计算内容与兴趣的匹配度
|
||||
|
||||
Args:
|
||||
content: 消息内容
|
||||
keywords: 关键词列表
|
||||
|
||||
Returns:
|
||||
匹配结果
|
||||
"""
|
||||
return await interest_service.calculate_interest_match(content, keywords)
|
||||
|
||||
@staticmethod
|
||||
def get_system_stats() -> dict[str, Any]:
|
||||
"""
|
||||
获取系统统计信息
|
||||
|
||||
Returns:
|
||||
包含各子系统统计的字典
|
||||
"""
|
||||
return {
|
||||
"relationship_service": relationship_service.get_cache_stats(),
|
||||
"interest_service": interest_service.get_interest_stats()
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def clear_caches(user_id: str = None):
|
||||
"""
|
||||
清理缓存
|
||||
|
||||
Args:
|
||||
user_id: 特定用户ID,如果为None则清理所有缓存
|
||||
"""
|
||||
relationship_service.clear_cache(user_id)
|
||||
logger.info(f"清理缓存: {user_id if user_id else '全部'}")
|
||||
|
||||
|
||||
# 创建全局API实例 - 系统级服务
|
||||
scoring_api = ScoringAPI()
|
||||
108
src/plugin_system/services/interest_service.py
Normal file
108
src/plugin_system/services/interest_service.py
Normal file
@@ -0,0 +1,108 @@
|
||||
"""
|
||||
兴趣系统服务
|
||||
提供独立的兴趣管理功能,不依赖任何插件
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from src.chat.interest_system import bot_interest_manager
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("interest_service")
|
||||
|
||||
|
||||
class InterestService:
|
||||
"""兴趣系统服务 - 独立于插件的兴趣管理"""
|
||||
|
||||
def __init__(self):
|
||||
self.is_initialized = bot_interest_manager.is_initialized
|
||||
|
||||
async def initialize_smart_interests(self, personality_description: str, personality_id: str = "default"):
|
||||
"""
|
||||
初始化智能兴趣系统
|
||||
|
||||
Args:
|
||||
personality_description: 机器人性格描述
|
||||
personality_id: 性格ID
|
||||
"""
|
||||
try:
|
||||
logger.info("开始初始化智能兴趣系统...")
|
||||
logger.info(f"人设ID: {personality_id}, 描述长度: {len(personality_description)}")
|
||||
|
||||
await bot_interest_manager.initialize(personality_description, personality_id)
|
||||
self.is_initialized = True
|
||||
logger.info("智能兴趣系统初始化完成。")
|
||||
|
||||
# 显示初始化后的统计信息
|
||||
stats = bot_interest_manager.get_interest_stats()
|
||||
logger.info(f"兴趣系统统计: {stats}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"初始化智能兴趣系统失败: {e}")
|
||||
self.is_initialized = False
|
||||
|
||||
async def calculate_interest_match(self, content: str, keywords: Optional[list[str]] = None):
|
||||
"""
|
||||
计算内容与兴趣的匹配度
|
||||
|
||||
Args:
|
||||
content: 消息内容
|
||||
keywords: 关键词列表
|
||||
|
||||
Returns:
|
||||
匹配结果
|
||||
"""
|
||||
if not self.is_initialized:
|
||||
logger.warning("兴趣系统未初始化,无法计算匹配度")
|
||||
return None
|
||||
|
||||
try:
|
||||
if not keywords:
|
||||
# 如果没有关键词,尝试从内容提取
|
||||
keywords = self._extract_keywords_from_content(content)
|
||||
|
||||
return await bot_interest_manager.calculate_interest_match(content, keywords)
|
||||
except Exception as e:
|
||||
logger.error(f"计算兴趣匹配度失败: {e}")
|
||||
return None
|
||||
|
||||
def _extract_keywords_from_content(self, content: str) -> list[str]:
|
||||
"""从内容中提取关键词"""
|
||||
import re
|
||||
|
||||
# 清理文本
|
||||
content = re.sub(r"[^\w\s\u4e00-\u9fff]", " ", content) # 保留中文、英文、数字
|
||||
words = content.split()
|
||||
|
||||
# 过滤和关键词提取
|
||||
keywords = []
|
||||
for word in words:
|
||||
word = word.strip()
|
||||
if (
|
||||
len(word) >= 2 # 至少2个字符
|
||||
and word.isalnum() # 字母数字
|
||||
and not word.isdigit()
|
||||
): # 不是纯数字
|
||||
keywords.append(word.lower())
|
||||
|
||||
# 去重并限制数量
|
||||
unique_keywords = list(set(keywords))
|
||||
return unique_keywords[:10] # 返回前10个唯一关键词
|
||||
|
||||
def get_interest_stats(self) -> dict:
|
||||
"""获取兴趣系统统计信息"""
|
||||
if not self.is_initialized:
|
||||
return {"initialized": False}
|
||||
|
||||
try:
|
||||
return {
|
||||
"initialized": True,
|
||||
**bot_interest_manager.get_interest_stats()
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"获取兴趣系统统计失败: {e}")
|
||||
return {"initialized": True, "error": str(e)}
|
||||
|
||||
|
||||
# 创建全局实例
|
||||
interest_service = InterestService()
|
||||
232
src/plugin_system/services/relationship_service.py
Normal file
232
src/plugin_system/services/relationship_service.py
Normal file
@@ -0,0 +1,232 @@
|
||||
"""
|
||||
用户关系分服务
|
||||
提供独立的关系分获取和管理功能,不依赖任何插件
|
||||
"""
|
||||
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
from src.common.database.sqlalchemy_models import UserRelationships, get_db_session
|
||||
from src.common.logger import get_logger
|
||||
from src.config.config import global_config
|
||||
|
||||
logger = get_logger("relationship_service")
|
||||
|
||||
|
||||
class RelationshipService:
|
||||
"""用户关系分服务 - 独立于插件的数据库直接访问层"""
|
||||
|
||||
def __init__(self):
|
||||
self._cache: dict[str, dict] = {} # user_id -> {score, text, last_updated}
|
||||
self._cache_ttl = 300 # 缓存5分钟
|
||||
|
||||
async def get_user_relationship_score(self, user_id: str) -> float:
|
||||
"""
|
||||
获取用户关系分
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
|
||||
Returns:
|
||||
关系分 (0.0 - 1.0)
|
||||
"""
|
||||
try:
|
||||
# 先检查缓存
|
||||
cached_data = self._get_from_cache(user_id)
|
||||
if cached_data is not None:
|
||||
return cached_data["score"]
|
||||
|
||||
# 从数据库获取
|
||||
relationship_data = await self._fetch_from_database(user_id)
|
||||
if relationship_data:
|
||||
score = relationship_data.relationship_score
|
||||
# 更新缓存
|
||||
self._update_cache(user_id, score, relationship_data.relationship_text)
|
||||
logger.debug(f"从数据库获取用户关系分: {user_id} -> {score:.3f}")
|
||||
return max(0.0, min(1.0, score))
|
||||
else:
|
||||
# 用户不存在,返回默认分数并创建记录
|
||||
default_score = global_config.affinity_flow.base_relationship_score
|
||||
await self._create_default_relationship(user_id)
|
||||
self._update_cache(user_id, default_score, "新用户")
|
||||
logger.debug(f"创建默认关系分: {user_id} -> {default_score:.3f}")
|
||||
return default_score
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取用户关系分失败: {user_id}, 错误: {e}")
|
||||
return global_config.affinity_flow.base_relationship_score
|
||||
|
||||
async def get_user_relationship_data(self, user_id: str) -> dict:
|
||||
"""
|
||||
获取用户完整关系数据
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
|
||||
Returns:
|
||||
包含关系分、关系文本等的字典
|
||||
"""
|
||||
try:
|
||||
# 先检查缓存
|
||||
cached_data = self._get_from_cache(user_id)
|
||||
if cached_data is not None:
|
||||
return {
|
||||
"relationship_score": cached_data["score"],
|
||||
"relationship_text": cached_data["text"],
|
||||
"last_updated": cached_data["last_updated"]
|
||||
}
|
||||
|
||||
# 从数据库获取
|
||||
relationship_data = await self._fetch_from_database(user_id)
|
||||
if relationship_data:
|
||||
result = {
|
||||
"relationship_score": relationship_data.relationship_score,
|
||||
"relationship_text": relationship_data.relationship_text or "",
|
||||
"last_updated": relationship_data.last_updated,
|
||||
"user_name": relationship_data.user_name or ""
|
||||
}
|
||||
# 更新缓存
|
||||
self._update_cache(user_id, result["relationship_score"], result["relationship_text"])
|
||||
return result
|
||||
else:
|
||||
# 创建默认记录
|
||||
default_score = global_config.affinity_flow.base_relationship_score
|
||||
await self._create_default_relationship(user_id)
|
||||
default_result = {
|
||||
"relationship_score": default_score,
|
||||
"relationship_text": "新用户",
|
||||
"last_updated": time.time(),
|
||||
"user_name": ""
|
||||
}
|
||||
self._update_cache(user_id, default_score, "新用户")
|
||||
return default_result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取用户关系数据失败: {user_id}, 错误: {e}")
|
||||
return {
|
||||
"relationship_score": global_config.affinity_flow.base_relationship_score,
|
||||
"relationship_text": "新用户",
|
||||
"last_updated": time.time(),
|
||||
"user_name": ""
|
||||
}
|
||||
|
||||
async def update_user_relationship(self, user_id: str, relationship_score: float, relationship_text: Optional[str] = None, user_name: Optional[str] = None):
|
||||
"""
|
||||
更新用户关系数据
|
||||
|
||||
Args:
|
||||
user_id: 用户ID
|
||||
relationship_score: 关系分 (0.0 - 1.0)
|
||||
relationship_text: 关系描述文本
|
||||
user_name: 用户名称
|
||||
"""
|
||||
try:
|
||||
# 限制分数范围
|
||||
score = max(0.0, min(1.0, relationship_score))
|
||||
|
||||
async with get_db_session() as session:
|
||||
# 查找现有记录
|
||||
from sqlalchemy import select
|
||||
stmt = select(UserRelationships).where(UserRelationships.user_id == user_id)
|
||||
result = await session.execute(stmt)
|
||||
existing = result.scalar_one_or_none()
|
||||
|
||||
if existing:
|
||||
# 更新现有记录
|
||||
existing.relationship_score = score
|
||||
existing.last_updated = time.time()
|
||||
if relationship_text is not None:
|
||||
existing.relationship_text = relationship_text
|
||||
if user_name is not None:
|
||||
existing.user_name = user_name
|
||||
logger.debug(f"更新用户关系: {user_id} -> {score:.3f}")
|
||||
else:
|
||||
# 创建新记录
|
||||
new_relationship = UserRelationships(
|
||||
user_id=user_id,
|
||||
user_name=user_name or "",
|
||||
relationship_text=relationship_text or "新用户",
|
||||
relationship_score=score,
|
||||
last_updated=time.time()
|
||||
)
|
||||
session.add(new_relationship)
|
||||
logger.debug(f"创建用户关系: {user_id} -> {score:.3f}")
|
||||
|
||||
await session.commit()
|
||||
|
||||
# 更新缓存
|
||||
self._update_cache(user_id, score, relationship_text or "新用户")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"更新用户关系失败: {user_id}, 错误: {e}")
|
||||
|
||||
def _get_from_cache(self, user_id: str) -> Optional[dict]:
|
||||
"""从缓存获取数据"""
|
||||
if user_id in self._cache:
|
||||
cached_data = self._cache[user_id]
|
||||
if time.time() - cached_data["last_updated"] < self._cache_ttl:
|
||||
return cached_data
|
||||
else:
|
||||
# 缓存过期,删除
|
||||
del self._cache[user_id]
|
||||
return None
|
||||
|
||||
def _update_cache(self, user_id: str, score: float, text: str):
|
||||
"""更新缓存"""
|
||||
self._cache[user_id] = {
|
||||
"score": score,
|
||||
"text": text,
|
||||
"last_updated": time.time()
|
||||
}
|
||||
|
||||
async def _fetch_from_database(self, user_id: str) -> Optional[UserRelationships]:
|
||||
"""从数据库获取关系数据"""
|
||||
try:
|
||||
async with get_db_session() as session:
|
||||
from sqlalchemy import select
|
||||
stmt = select(UserRelationships).where(UserRelationships.user_id == user_id)
|
||||
result = await session.execute(stmt)
|
||||
return result.scalar_one_or_none()
|
||||
except Exception as e:
|
||||
logger.error(f"从数据库获取关系数据失败: {user_id}, 错误: {e}")
|
||||
return None
|
||||
|
||||
async def _create_default_relationship(self, user_id: str):
|
||||
"""创建默认关系记录"""
|
||||
try:
|
||||
default_score = global_config.affinity_flow.base_relationship_score
|
||||
async with get_db_session() as session:
|
||||
new_relationship = UserRelationships(
|
||||
user_id=user_id,
|
||||
user_name="",
|
||||
relationship_text="新用户",
|
||||
relationship_score=default_score,
|
||||
last_updated=time.time()
|
||||
)
|
||||
session.add(new_relationship)
|
||||
await session.commit()
|
||||
logger.debug(f"创建默认关系记录: {user_id} -> {default_score:.3f}")
|
||||
except Exception as e:
|
||||
logger.error(f"创建默认关系记录失败: {user_id}, 错误: {e}")
|
||||
|
||||
def get_cache_stats(self) -> dict:
|
||||
"""获取缓存统计信息"""
|
||||
return {
|
||||
"cached_users": len(self._cache),
|
||||
"cache_ttl": self._cache_ttl,
|
||||
"cache_keys": list(self._cache.keys())
|
||||
}
|
||||
|
||||
def clear_cache(self, user_id: Optional[str] = None):
|
||||
"""清理缓存"""
|
||||
if user_id:
|
||||
if user_id in self._cache:
|
||||
del self._cache[user_id]
|
||||
logger.debug(f"清理用户缓存: {user_id}")
|
||||
else:
|
||||
self._cache.clear()
|
||||
logger.debug("清理所有缓存")
|
||||
|
||||
|
||||
# 创建全局实例
|
||||
relationship_service = RelationshipService()
|
||||
Reference in New Issue
Block a user