refactor(affinity_flow): 重构规划器架构并简化日志输出
- 移除ChatterManager中不必要的ActionPlanner实例化 - 在MessageManager中设置默认聊天模式为FOCUS - 重构BaseChatter构造函数,移除planner依赖 - 统一ChatMode枚举定义,移除GROUP/PRIVATE模式 - 重构AffinityChatter内部planner初始化逻辑 - 大幅简化兴趣评分系统的日志输出 - 修复plan_filter中的动作解析逻辑,支持新格式 - 更新planner_prompts提示词模板,移除私聊限制 - 优化关系追踪器的错误处理和日志输出
This commit is contained in:
@@ -99,8 +99,7 @@ class ChatterManager:
|
|||||||
raise ValueError(f"No chatter registered for chat type {chat_type}")
|
raise ValueError(f"No chatter registered for chat type {chat_type}")
|
||||||
|
|
||||||
if stream_id not in self.instances:
|
if stream_id not in self.instances:
|
||||||
planner = ActionPlanner(stream_id, self.action_manager)
|
self.instances[stream_id] = chatter_class(stream_id=stream_id, action_manager=self.action_manager)
|
||||||
self.instances[stream_id] = chatter_class(stream_id=stream_id, planner=planner, action_manager=self.action_manager)
|
|
||||||
logger.info(f"创建新的聊天流实例: {stream_id} 使用 {chatter_class.__name__} (类型: {chat_type.value})")
|
logger.info(f"创建新的聊天流实例: {stream_id} 使用 {chatter_class.__name__} (类型: {chat_type.value})")
|
||||||
|
|
||||||
self.stats["streams_processed"] += 1
|
self.stats["streams_processed"] += 1
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from src.common.data_models.database_data_model import DatabaseMessages
|
|||||||
from src.common.data_models.message_manager_data_model import StreamContext, MessageManagerStats, StreamStats
|
from src.common.data_models.message_manager_data_model import StreamContext, MessageManagerStats, StreamStats
|
||||||
from src.chat.chatter_manager import ChatterManager
|
from src.chat.chatter_manager import ChatterManager
|
||||||
from src.chat.planner_actions.action_manager import ChatterActionManager
|
from src.chat.planner_actions.action_manager import ChatterActionManager
|
||||||
|
from src.plugin_system.base.component_types import ChatMode
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from src.common.data_models.message_manager_data_model import StreamContext
|
from src.common.data_models.message_manager_data_model import StreamContext
|
||||||
@@ -72,6 +73,7 @@ class MessageManager:
|
|||||||
self.stats.total_streams += 1
|
self.stats.total_streams += 1
|
||||||
|
|
||||||
context = self.stream_contexts[stream_id]
|
context = self.stream_contexts[stream_id]
|
||||||
|
context.set_chat_mode(ChatMode.FOCUS)
|
||||||
context.add_message(message)
|
context.add_message(message)
|
||||||
|
|
||||||
logger.debug(f"添加消息到聊天流 {stream_id}: {message.message_id}")
|
logger.debug(f"添加消息到聊天流 {stream_id}: {message.message_id}")
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Optional, Dict, List, TYPE_CHECKING
|
from typing import Optional, Dict, List, TYPE_CHECKING
|
||||||
|
|
||||||
|
from src.plugin_system.base.component_types import ChatType
|
||||||
from . import BaseDataModel
|
from . import BaseDataModel
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@@ -46,6 +48,7 @@ class Plan(BaseDataModel):
|
|||||||
chat_id: str
|
chat_id: str
|
||||||
mode: "ChatMode"
|
mode: "ChatMode"
|
||||||
|
|
||||||
|
chat_type: "ChatType"
|
||||||
# Generator 填充
|
# Generator 填充
|
||||||
available_actions: Dict[str, "ActionInfo"] = field(default_factory=dict)
|
available_actions: Dict[str, "ActionInfo"] = field(default_factory=dict)
|
||||||
chat_history: List["DatabaseMessages"] = field(default_factory=list)
|
chat_history: List["DatabaseMessages"] = field(default_factory=list)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from enum import Enum
|
|||||||
from typing import List, Optional, TYPE_CHECKING
|
from typing import List, Optional, TYPE_CHECKING
|
||||||
|
|
||||||
from . import BaseDataModel
|
from . import BaseDataModel
|
||||||
from src.plugin_system.base.component_types import ChatType
|
from src.plugin_system.base.component_types import ChatMode, ChatType
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .database_data_model import DatabaseMessages
|
from .database_data_model import DatabaseMessages
|
||||||
@@ -30,6 +30,7 @@ class StreamContext(BaseDataModel):
|
|||||||
|
|
||||||
stream_id: str
|
stream_id: str
|
||||||
chat_type: ChatType = ChatType.PRIVATE # 聊天类型,默认为私聊
|
chat_type: ChatType = ChatType.PRIVATE # 聊天类型,默认为私聊
|
||||||
|
chat_mode: ChatMode = ChatMode.NORMAL # 聊天模式,默认为普通模式
|
||||||
unread_messages: List["DatabaseMessages"] = field(default_factory=list)
|
unread_messages: List["DatabaseMessages"] = field(default_factory=list)
|
||||||
history_messages: List["DatabaseMessages"] = field(default_factory=list)
|
history_messages: List["DatabaseMessages"] = field(default_factory=list)
|
||||||
last_check_time: float = field(default_factory=time.time)
|
last_check_time: float = field(default_factory=time.time)
|
||||||
@@ -60,6 +61,10 @@ class StreamContext(BaseDataModel):
|
|||||||
"""手动更新聊天类型"""
|
"""手动更新聊天类型"""
|
||||||
self.chat_type = chat_type
|
self.chat_type = chat_type
|
||||||
|
|
||||||
|
def set_chat_mode(self, chat_mode: ChatMode):
|
||||||
|
"""设置聊天模式"""
|
||||||
|
self.chat_mode = chat_mode
|
||||||
|
|
||||||
def is_group_chat(self) -> bool:
|
def is_group_chat(self) -> bool:
|
||||||
"""检查是否为群聊"""
|
"""检查是否为群聊"""
|
||||||
return self.chat_type == ChatType.GROUP
|
return self.chat_type == ChatType.GROUP
|
||||||
|
|||||||
@@ -15,17 +15,15 @@ class BaseChatter(ABC):
|
|||||||
"""Chatter组件的描述"""
|
"""Chatter组件的描述"""
|
||||||
chat_types: List[ChatType] = [ChatType.PRIVATE, ChatType.GROUP]
|
chat_types: List[ChatType] = [ChatType.PRIVATE, ChatType.GROUP]
|
||||||
|
|
||||||
def __init__(self, stream_id: str, planner: 'ActionPlanner', action_manager: 'ChatterActionManager'):
|
def __init__(self, stream_id: str, action_manager: 'ChatterActionManager'):
|
||||||
"""
|
"""
|
||||||
初始化聊天处理器
|
初始化聊天处理器
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
stream_id: 聊天流ID
|
stream_id: 聊天流ID
|
||||||
planner: 动作规划器
|
|
||||||
action_manager: 动作管理器
|
action_manager: 动作管理器
|
||||||
"""
|
"""
|
||||||
self.stream_id = stream_id
|
self.stream_id = stream_id
|
||||||
self.planner = planner
|
|
||||||
self.action_manager = action_manager
|
self.action_manager = action_manager
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ class ActionActivationType(Enum):
|
|||||||
class ChatMode(Enum):
|
class ChatMode(Enum):
|
||||||
"""聊天模式枚举"""
|
"""聊天模式枚举"""
|
||||||
|
|
||||||
GROUP = "group" # 群聊模式
|
FOCUS = "focus" # 专注模式
|
||||||
PRIVATE = "private" # 私聊模式
|
|
||||||
NORMAL = "normal" # Normal聊天模式
|
NORMAL = "normal" # Normal聊天模式
|
||||||
PROACTIVE = "proactive" # 主动思考模式
|
PROACTIVE = "proactive" # 主动思考模式
|
||||||
PRIORITY = "priority" # 优先级聊天模式
|
PRIORITY = "priority" # 优先级聊天模式
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ from datetime import datetime
|
|||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
|
|
||||||
from src.plugin_system.base.base_chatter import BaseChatter
|
from src.plugin_system.base.base_chatter import BaseChatter
|
||||||
from src.plugin_system.base.component_types import ChatType, ChatMode
|
from src.plugin_system.base.component_types import ChatType
|
||||||
from src.common.data_models.message_manager_data_model import StreamContext
|
from src.common.data_models.message_manager_data_model import StreamContext
|
||||||
from src.plugins.built_in.affinity_flow_chatter.planner import ChatterActionPlanner as ActionPlanner
|
from src.plugins.built_in.affinity_flow_chatter.planner import ChatterActionPlanner
|
||||||
from src.chat.planner_actions.action_manager import ChatterActionManager
|
from src.chat.planner_actions.action_manager import ChatterActionManager
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
|
|
||||||
@@ -20,11 +20,12 @@ logger = get_logger("affinity_chatter")
|
|||||||
|
|
||||||
class AffinityChatter(BaseChatter):
|
class AffinityChatter(BaseChatter):
|
||||||
"""亲和力聊天处理器"""
|
"""亲和力聊天处理器"""
|
||||||
|
|
||||||
chatter_name: str = "AffinityChatter"
|
chatter_name: str = "AffinityChatter"
|
||||||
chatter_description: str = "基于亲和力模型的智能聊天处理器,支持多种聊天类型"
|
chatter_description: str = "基于亲和力模型的智能聊天处理器,支持多种聊天类型"
|
||||||
chat_types: list[ChatType] = [ChatType.ALL] # 支持所有聊天类型
|
chat_types: list[ChatType] = [ChatType.ALL] # 支持所有聊天类型
|
||||||
|
|
||||||
def __init__(self, stream_id: str, planner: ActionPlanner, action_manager: ChatterActionManager):
|
def __init__(self, stream_id: str, action_manager: ChatterActionManager):
|
||||||
"""
|
"""
|
||||||
初始化亲和力聊天处理器
|
初始化亲和力聊天处理器
|
||||||
|
|
||||||
@@ -33,7 +34,8 @@ class AffinityChatter(BaseChatter):
|
|||||||
planner: 动作规划器
|
planner: 动作规划器
|
||||||
action_manager: 动作管理器
|
action_manager: 动作管理器
|
||||||
"""
|
"""
|
||||||
super().__init__(stream_id, planner, action_manager)
|
super().__init__(stream_id, action_manager)
|
||||||
|
self.planner = ChatterActionPlanner(stream_id, action_manager)
|
||||||
|
|
||||||
# 处理器统计
|
# 处理器统计
|
||||||
self.stats = {
|
self.stats = {
|
||||||
@@ -59,7 +61,7 @@ class AffinityChatter(BaseChatter):
|
|||||||
unread_messages = context.get_unread_messages()
|
unread_messages = context.get_unread_messages()
|
||||||
|
|
||||||
# 使用增强版规划器处理消息
|
# 使用增强版规划器处理消息
|
||||||
actions, target_message = await self.planner.plan(mode=ChatMode.GROUP, context=context)
|
actions, target_message = await self.planner.plan(context=context)
|
||||||
self.stats["plans_created"] += 1
|
self.stats["plans_created"] += 1
|
||||||
|
|
||||||
# 执行动作(如果规划器返回了动作)
|
# 执行动作(如果规划器返回了动作)
|
||||||
|
|||||||
@@ -52,21 +52,16 @@ class ChatterInterestScoringSystem:
|
|||||||
user_messages = [msg for msg in messages if str(msg.user_info.user_id) != str(global_config.bot.qq_account)]
|
user_messages = [msg for msg in messages if str(msg.user_info.user_id) != str(global_config.bot.qq_account)]
|
||||||
if not user_messages:
|
if not user_messages:
|
||||||
return []
|
return []
|
||||||
logger.info(f"正在为 {len(user_messages)} 条用户消息计算兴趣度...")
|
|
||||||
|
|
||||||
scores = []
|
scores = []
|
||||||
for i, msg in enumerate(user_messages, 1):
|
for _, msg in enumerate(user_messages, 1):
|
||||||
logger.debug(f"[{i}/{len(user_messages)}] 处理消息 ID: {msg.message_id}")
|
|
||||||
score = await self._calculate_single_message_score(msg, bot_nickname)
|
score = await self._calculate_single_message_score(msg, bot_nickname)
|
||||||
scores.append(score)
|
scores.append(score)
|
||||||
|
|
||||||
logger.info(f"为 {len(scores)} 条消息生成了兴趣度评分。")
|
|
||||||
return scores
|
return scores
|
||||||
|
|
||||||
async def _calculate_single_message_score(self, message: DatabaseMessages, bot_nickname: str) -> InterestScore:
|
async def _calculate_single_message_score(self, message: DatabaseMessages, bot_nickname: str) -> InterestScore:
|
||||||
"""计算单条消息的兴趣度评分"""
|
"""计算单条消息的兴趣度评分"""
|
||||||
message_preview = f"\033[96m{message.processed_plain_text[:30].replace('\n', ' ')}...\033[0m"
|
|
||||||
logger.info(f"计算消息 {message.message_id} 的分数 | 内容: {message_preview}")
|
|
||||||
|
|
||||||
keywords = self._extract_keywords_from_database(message)
|
keywords = self._extract_keywords_from_database(message)
|
||||||
interest_match_score = await self._calculate_interest_match_score(message.processed_plain_text, keywords)
|
interest_match_score = await self._calculate_interest_match_score(message.processed_plain_text, keywords)
|
||||||
@@ -86,8 +81,7 @@ class ChatterInterestScoringSystem:
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"消息 {message.message_id} 得分: {total_score:.3f} "
|
f"消息得分: {total_score:.3f} (匹配: {interest_match_score:.2f}, 关系: {relationship_score:.2f}, 提及: {mentioned_score:.2f})"
|
||||||
f"(匹配: {interest_match_score:.2f}, 关系: {relationship_score:.2f}, 提及: {mentioned_score:.2f})"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return InterestScore(
|
return InterestScore(
|
||||||
@@ -109,51 +103,31 @@ class ChatterInterestScoringSystem:
|
|||||||
return await self._calculate_smart_interest_match(content, keywords)
|
return await self._calculate_smart_interest_match(content, keywords)
|
||||||
else:
|
else:
|
||||||
# 智能匹配未初始化,返回默认分数
|
# 智能匹配未初始化,返回默认分数
|
||||||
logger.warning("智能兴趣匹配系统未初始化,返回默认分数")
|
|
||||||
return 0.3
|
return 0.3
|
||||||
|
|
||||||
async def _calculate_smart_interest_match(self, content: str, keywords: List[str] = None) -> float:
|
async def _calculate_smart_interest_match(self, content: str, keywords: List[str] = None) -> float:
|
||||||
"""使用embedding计算智能兴趣匹配"""
|
"""使用embedding计算智能兴趣匹配"""
|
||||||
try:
|
try:
|
||||||
logger.debug("🧠 开始智能兴趣匹配计算...")
|
|
||||||
|
|
||||||
# 如果没有传入关键词,则提取
|
# 如果没有传入关键词,则提取
|
||||||
if not keywords:
|
if not keywords:
|
||||||
logger.debug("🔍 从内容中提取关键词...")
|
|
||||||
keywords = self._extract_keywords_from_content(content)
|
keywords = self._extract_keywords_from_content(content)
|
||||||
logger.debug(f"🏷️ 提取到 {len(keywords)} 个关键词")
|
|
||||||
|
|
||||||
# 使用机器人兴趣管理器计算匹配度
|
# 使用机器人兴趣管理器计算匹配度
|
||||||
logger.debug("🤖 调用机器人兴趣管理器计算匹配度...")
|
|
||||||
match_result = await bot_interest_manager.calculate_interest_match(content, keywords)
|
match_result = await bot_interest_manager.calculate_interest_match(content, keywords)
|
||||||
|
|
||||||
if match_result:
|
if match_result:
|
||||||
logger.debug("✅ 智能兴趣匹配成功:")
|
|
||||||
logger.debug(f" 📊 总分: {match_result.overall_score:.3f}")
|
|
||||||
logger.debug(f" 🏷️ 匹配标签: {match_result.matched_tags}")
|
|
||||||
logger.debug(f" 🎯 最佳标签: {match_result.top_tag}")
|
|
||||||
logger.debug(f" 📈 置信度: {match_result.confidence:.3f}")
|
|
||||||
logger.debug(f" 🔢 匹配详情: {match_result.match_scores}")
|
|
||||||
|
|
||||||
# 返回匹配分数,考虑置信度和匹配标签数量
|
# 返回匹配分数,考虑置信度和匹配标签数量
|
||||||
affinity_config = global_config.affinity_flow
|
affinity_config = global_config.affinity_flow
|
||||||
match_count_bonus = min(
|
match_count_bonus = min(
|
||||||
len(match_result.matched_tags) * affinity_config.match_count_bonus, affinity_config.max_match_bonus
|
len(match_result.matched_tags) * affinity_config.match_count_bonus, affinity_config.max_match_bonus
|
||||||
)
|
)
|
||||||
final_score = match_result.overall_score * 1.15 * match_result.confidence + match_count_bonus
|
final_score = match_result.overall_score * 1.15 * match_result.confidence + match_count_bonus
|
||||||
logger.debug(
|
|
||||||
f"⚖️ 最终分数计算: 总分({match_result.overall_score:.3f}) × 1.3 × 置信度({match_result.confidence:.3f}) + 标签数量奖励({match_count_bonus:.3f}) = {final_score:.3f}"
|
|
||||||
)
|
|
||||||
return final_score
|
return final_score
|
||||||
else:
|
else:
|
||||||
logger.warning("⚠️ 智能兴趣匹配未返回结果")
|
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"❌ 智能兴趣匹配计算失败: {e}")
|
logger.error(f"智能兴趣匹配计算失败: {e}")
|
||||||
logger.debug("🔍 错误详情:")
|
|
||||||
logger.debug(f" 💬 内容长度: {len(content)} 字符")
|
|
||||||
logger.debug(f" 🏷️ 关键词数量: {len(keywords) if keywords else 0}")
|
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
def _extract_keywords_from_database(self, message: DatabaseMessages) -> List[str]:
|
def _extract_keywords_from_database(self, message: DatabaseMessages) -> List[str]:
|
||||||
@@ -225,8 +199,8 @@ class ChatterInterestScoringSystem:
|
|||||||
# 同时更新内存缓存
|
# 同时更新内存缓存
|
||||||
self.user_relationships[user_id] = relationship_score
|
self.user_relationships[user_id] = relationship_score
|
||||||
return relationship_score
|
return relationship_score
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logger.warning(f"从关系追踪器获取关系分失败: {e}")
|
pass
|
||||||
else:
|
else:
|
||||||
# 尝试从全局关系追踪器获取
|
# 尝试从全局关系追踪器获取
|
||||||
try:
|
try:
|
||||||
@@ -238,8 +212,8 @@ class ChatterInterestScoringSystem:
|
|||||||
# 同时更新内存缓存
|
# 同时更新内存缓存
|
||||||
self.user_relationships[user_id] = relationship_score
|
self.user_relationships[user_id] = relationship_score
|
||||||
return relationship_score
|
return relationship_score
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logger.warning(f"从全局关系追踪器获取关系分失败: {e}")
|
pass
|
||||||
|
|
||||||
# 默认新用户的基础分
|
# 默认新用户的基础分
|
||||||
return global_config.affinity_flow.base_relationship_score
|
return global_config.affinity_flow.base_relationship_score
|
||||||
@@ -261,26 +235,20 @@ class ChatterInterestScoringSystem:
|
|||||||
|
|
||||||
def should_reply(self, score: InterestScore, message: "DatabaseMessages") -> bool:
|
def should_reply(self, score: InterestScore, message: "DatabaseMessages") -> bool:
|
||||||
"""判断是否应该回复"""
|
"""判断是否应该回复"""
|
||||||
message_preview = f"\033[96m{(message.processed_plain_text or 'N/A')[:50].replace('\n', ' ')}\033[0m"
|
|
||||||
logger.info(f"评估消息 {score.message_id} (得分: {score.total_score:.3f}) | 内容: '{message_preview}...'")
|
|
||||||
base_threshold = self.reply_threshold
|
base_threshold = self.reply_threshold
|
||||||
|
|
||||||
# 如果被提及,降低阈值
|
# 如果被提及,降低阈值
|
||||||
if score.mentioned_score >= global_config.affinity_flow.mention_bot_adjustment_threshold:
|
if score.mentioned_score >= global_config.affinity_flow.mention_bot_adjustment_threshold:
|
||||||
base_threshold = self.mention_threshold
|
base_threshold = self.mention_threshold
|
||||||
logger.debug(f"机器人被提及, 使用较低阈值: {base_threshold:.3f}")
|
|
||||||
|
|
||||||
# 计算连续不回复的概率提升
|
# 计算连续不回复的概率提升
|
||||||
probability_boost = min(self.no_reply_count * self.probability_boost_per_no_reply, 0.8)
|
probability_boost = min(self.no_reply_count * self.probability_boost_per_no_reply, 0.8)
|
||||||
effective_threshold = base_threshold - probability_boost
|
effective_threshold = base_threshold - probability_boost
|
||||||
logger.debug(
|
|
||||||
f"基础阈值: {base_threshold:.3f}, 不回复提升: {probability_boost:.3f}, 有效阈值: {effective_threshold:.3f}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# 做出决策
|
# 做出决策
|
||||||
should_reply = score.total_score >= effective_threshold
|
should_reply = score.total_score >= effective_threshold
|
||||||
decision = "✅ 回复" if should_reply else "❌ 不回复"
|
decision = "回复" if should_reply else "不回复"
|
||||||
logger.info(f"回复决策: {decision} (分数: {score.total_score:.3f} {' >=' if should_reply else ' <'} 阈值: {effective_threshold:.3f})")
|
logger.info(f"决策: {decision} (分数: {score.total_score:.3f})")
|
||||||
|
|
||||||
return should_reply, score.total_score
|
return should_reply, score.total_score
|
||||||
|
|
||||||
@@ -296,8 +264,7 @@ class ChatterInterestScoringSystem:
|
|||||||
|
|
||||||
# 限制最大计数
|
# 限制最大计数
|
||||||
self.no_reply_count = min(self.no_reply_count, self.max_no_reply_count)
|
self.no_reply_count = min(self.no_reply_count, self.max_no_reply_count)
|
||||||
logger.info(f"记录动作: {action} | 连续不回复次数: {old_count} -> {self.no_reply_count}")
|
logger.info(f"{action} | 不回复次数: {old_count} -> {self.no_reply_count}")
|
||||||
logger.debug(f"📋 最大限制: {self.max_no_reply_count} 次")
|
|
||||||
|
|
||||||
def update_user_relationship(self, user_id: str, relationship_change: float):
|
def update_user_relationship(self, user_id: str, relationship_change: float):
|
||||||
"""更新用户关系"""
|
"""更新用户关系"""
|
||||||
@@ -308,10 +275,7 @@ class ChatterInterestScoringSystem:
|
|||||||
|
|
||||||
self.user_relationships[user_id] = new_score
|
self.user_relationships[user_id] = new_score
|
||||||
|
|
||||||
change_direction = "📈" if relationship_change > 0 else "📉" if relationship_change < 0 else "➖"
|
logger.info(f"用户关系: {user_id} | {old_score:.3f} → {new_score:.3f}")
|
||||||
logger.info(f"{change_direction} 更新用户关系: {user_id}")
|
|
||||||
logger.info(f"💝 关系分: {old_score:.3f} → {new_score:.3f} (变化: {relationship_change:+.3f})")
|
|
||||||
logger.debug(f"👥 当前追踪用户数: {len(self.user_relationships)}")
|
|
||||||
|
|
||||||
def get_user_relationship(self, user_id: str) -> float:
|
def get_user_relationship(self, user_id: str) -> float:
|
||||||
"""获取用户关系分"""
|
"""获取用户关系分"""
|
||||||
@@ -342,12 +306,7 @@ class ChatterInterestScoringSystem:
|
|||||||
logger.info("智能兴趣系统初始化完成。")
|
logger.info("智能兴趣系统初始化完成。")
|
||||||
|
|
||||||
# 显示初始化后的统计信息
|
# 显示初始化后的统计信息
|
||||||
stats = bot_interest_manager.get_interest_stats()
|
bot_interest_manager.get_interest_stats()
|
||||||
logger.info(
|
|
||||||
f"兴趣系统统计: 总标签={stats.get('total_tags', 0)}, "
|
|
||||||
f"缓存大小={stats.get('cache_size', 0)}, "
|
|
||||||
f"模型='{stats.get('embedding_model', '未知')}'"
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"初始化智能兴趣系统失败: {e}")
|
logger.error(f"初始化智能兴趣系统失败: {e}")
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ PlanExecutor: 接收 Plan 对象并执行其中的所有动作。
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import re
|
|
||||||
import time
|
import time
|
||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from src.common.logger import get_logger
|
|||||||
from src.config.config import global_config, model_config
|
from src.config.config import global_config, model_config
|
||||||
from src.llm_models.utils_model import LLMRequest
|
from src.llm_models.utils_model import LLMRequest
|
||||||
from src.mood.mood_manager import mood_manager
|
from src.mood.mood_manager import mood_manager
|
||||||
from src.plugin_system.base.component_types import ActionInfo, ChatMode
|
from src.plugin_system.base.component_types import ActionInfo, ChatMode, ChatType
|
||||||
from src.schedule.schedule_manager import schedule_manager
|
from src.schedule.schedule_manager import schedule_manager
|
||||||
|
|
||||||
logger = get_logger("plan_filter")
|
logger = get_logger("plan_filter")
|
||||||
@@ -41,31 +41,33 @@ class ChatterPlanFilter:
|
|||||||
"""
|
"""
|
||||||
执行筛选逻辑,并填充 Plan 对象的 decided_actions 字段。
|
执行筛选逻辑,并填充 Plan 对象的 decided_actions 字段。
|
||||||
"""
|
"""
|
||||||
logger.debug(f"墨墨在这里加了日志 -> filter 入口 plan: {plan}")
|
|
||||||
try:
|
try:
|
||||||
prompt, used_message_id_list = await self._build_prompt(plan)
|
prompt, used_message_id_list = await self._build_prompt(plan)
|
||||||
plan.llm_prompt = prompt
|
plan.llm_prompt = prompt
|
||||||
logger.debug(f"墨墨在这里加了日志 -> LLM prompt: {prompt}")
|
|
||||||
|
|
||||||
llm_content, _ = await self.planner_llm.generate_response_async(prompt=prompt)
|
llm_content, _ = await self.planner_llm.generate_response_async(prompt=prompt)
|
||||||
|
|
||||||
if llm_content:
|
if llm_content:
|
||||||
logger.debug(f"墨墨在这里加了日志 -> LLM a原始返回: {llm_content}")
|
|
||||||
try:
|
try:
|
||||||
parsed_json = orjson.loads(repair_json(llm_content))
|
parsed_json = orjson.loads(repair_json(llm_content))
|
||||||
except orjson.JSONDecodeError:
|
except orjson.JSONDecodeError:
|
||||||
parsed_json = {"action": "no_action", "reason": "返回内容无法解析为JSON"}
|
parsed_json = {
|
||||||
logger.debug(f"墨墨在这里加了日志 -> 解析后的 JSON: {parsed_json}")
|
"thinking": "",
|
||||||
|
"actions": {"action_type": "no_action", "reason": "返回内容无法解析为JSON"},
|
||||||
|
}
|
||||||
|
|
||||||
if "reply" in plan.available_actions and reply_not_available:
|
if "reply" in plan.available_actions and reply_not_available:
|
||||||
# 如果reply动作不可用,但llm返回的仍然有reply,则改为no_reply
|
# 如果reply动作不可用,但llm返回的仍然有reply,则改为no_reply
|
||||||
if isinstance(parsed_json, dict) and parsed_json.get("action") == "reply":
|
if (
|
||||||
parsed_json["action"] = "no_reply"
|
isinstance(parsed_json, dict)
|
||||||
|
and parsed_json.get("actions", {}).get("action_type", "") == "reply"
|
||||||
|
):
|
||||||
|
parsed_json["actions"]["action_type"] = "no_reply"
|
||||||
elif isinstance(parsed_json, list):
|
elif isinstance(parsed_json, list):
|
||||||
for item in parsed_json:
|
for item in parsed_json:
|
||||||
if isinstance(item, dict) and item.get("action") == "reply":
|
if isinstance(item, dict) and item.get("actions", {}).get("action_type", "") == "reply":
|
||||||
item["action"] = "no_reply"
|
item["actions"]["action_type"] = "no_reply"
|
||||||
item["reason"] += " (但由于兴趣度不足,reply动作不可用,已改为no_reply)"
|
item["actions"]["reason"] += " (但由于兴趣度不足,reply动作不可用,已改为no_reply)"
|
||||||
|
|
||||||
if isinstance(parsed_json, dict):
|
if isinstance(parsed_json, dict):
|
||||||
parsed_json = [parsed_json]
|
parsed_json = [parsed_json]
|
||||||
@@ -81,23 +83,40 @@ class ChatterPlanFilter:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# 预解析 action_type 来进行判断
|
# 预解析 action_type 来进行判断
|
||||||
action_type = item.get("action", "no_action")
|
thinking = item.get("thinking", "未提供思考过程")
|
||||||
|
actions_obj = item.get("actions", {})
|
||||||
|
|
||||||
|
# 处理actions字段可能是字典或列表的情况
|
||||||
|
if isinstance(actions_obj, dict):
|
||||||
|
action_type = actions_obj.get("action_type", "no_action")
|
||||||
|
elif isinstance(actions_obj, list) and actions_obj:
|
||||||
|
# 如果是列表,取第一个元素的action_type
|
||||||
|
first_action = actions_obj[0]
|
||||||
|
if isinstance(first_action, dict):
|
||||||
|
action_type = first_action.get("action_type", "no_action")
|
||||||
|
else:
|
||||||
|
action_type = "no_action"
|
||||||
|
else:
|
||||||
|
action_type = "no_action"
|
||||||
|
|
||||||
if action_type in reply_action_types:
|
if action_type in reply_action_types:
|
||||||
if not reply_action_added:
|
if not reply_action_added:
|
||||||
final_actions.extend(await self._parse_single_action(item, used_message_id_list, plan))
|
final_actions.extend(
|
||||||
|
await self._parse_single_action(item, used_message_id_list, plan)
|
||||||
|
)
|
||||||
reply_action_added = True
|
reply_action_added = True
|
||||||
else:
|
else:
|
||||||
# 非回复类动作直接添加
|
# 非回复类动作直接添加
|
||||||
final_actions.extend(await self._parse_single_action(item, used_message_id_list, plan))
|
final_actions.extend(await self._parse_single_action(item, used_message_id_list, plan))
|
||||||
|
|
||||||
|
if thinking and thinking != "未提供思考过程":
|
||||||
|
logger.info(f"思考: {thinking}")
|
||||||
plan.decided_actions = self._filter_no_actions(final_actions)
|
plan.decided_actions = self._filter_no_actions(final_actions)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"筛选 Plan 时出错: {e}\n{traceback.format_exc()}")
|
logger.error(f"筛选 Plan 时出错: {e}\n{traceback.format_exc()}")
|
||||||
plan.decided_actions = [ActionPlannerInfo(action_type="no_action", reasoning=f"筛选时出错: {e}")]
|
plan.decided_actions = [ActionPlannerInfo(action_type="no_action", reasoning=f"筛选时出错: {e}")]
|
||||||
|
|
||||||
logger.debug(f"墨墨在这里加了日志 -> filter 出口 decided_actions: {plan.decided_actions}")
|
|
||||||
return plan
|
return plan
|
||||||
|
|
||||||
async def _build_prompt(self, plan: Plan) -> tuple[str, list]:
|
async def _build_prompt(self, plan: Plan) -> tuple[str, list]:
|
||||||
@@ -186,7 +205,7 @@ class ChatterPlanFilter:
|
|||||||
if global_config.chat.at_bot_inevitable_reply:
|
if global_config.chat.at_bot_inevitable_reply:
|
||||||
mentioned_bonus = "\n- 有人提到你,或者at你"
|
mentioned_bonus = "\n- 有人提到你,或者at你"
|
||||||
|
|
||||||
if plan.mode == ChatMode.GROUP:
|
if plan.mode == ChatMode.FOCUS:
|
||||||
no_action_block = """
|
no_action_block = """
|
||||||
动作:no_action
|
动作:no_action
|
||||||
动作描述:不选择任何动作
|
动作描述:不选择任何动作
|
||||||
@@ -204,7 +223,7 @@ class ChatterPlanFilter:
|
|||||||
"reason":"不回复的原因"
|
"reason":"不回复的原因"
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
else: # PRIVATE Mode
|
else: # normal Mode
|
||||||
no_action_block = """重要说明:
|
no_action_block = """重要说明:
|
||||||
- 'reply' 表示只进行普通聊天回复,不执行任何额外动作
|
- 'reply' 表示只进行普通聊天回复,不执行任何额外动作
|
||||||
- 其他action表示在普通回复的基础上,执行相应的额外动作
|
- 其他action表示在普通回复的基础上,执行相应的额外动作
|
||||||
@@ -214,7 +233,7 @@ class ChatterPlanFilter:
|
|||||||
"reason":"回复的原因"
|
"reason":"回复的原因"
|
||||||
}}"""
|
}}"""
|
||||||
|
|
||||||
is_group_chat = plan.target_info.platform == "group" if plan.target_info else True
|
is_group_chat = plan.chat_type == ChatType.GROUP
|
||||||
chat_context_description = "你现在正在一个群聊中"
|
chat_context_description = "你现在正在一个群聊中"
|
||||||
if not is_group_chat and plan.target_info:
|
if not is_group_chat and plan.target_info:
|
||||||
chat_target_name = plan.target_info.person_name or plan.target_info.user_nickname or "对方"
|
chat_target_name = plan.target_info.person_name or plan.target_info.user_nickname or "对方"
|
||||||
@@ -321,7 +340,9 @@ class ChatterPlanFilter:
|
|||||||
interest_scores = {}
|
interest_scores = {}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from src.plugins.built_in.affinity_flow_chatter.interest_scoring import chatter_interest_scoring_system as interest_scoring_system
|
from src.plugins.built_in.affinity_flow_chatter.interest_scoring import (
|
||||||
|
chatter_interest_scoring_system as interest_scoring_system,
|
||||||
|
)
|
||||||
from src.common.data_models.database_data_model import DatabaseMessages
|
from src.common.data_models.database_data_model import DatabaseMessages
|
||||||
|
|
||||||
# 转换消息格式
|
# 转换消息格式
|
||||||
@@ -364,13 +385,39 @@ class ChatterPlanFilter:
|
|||||||
) -> List[ActionPlannerInfo]:
|
) -> List[ActionPlannerInfo]:
|
||||||
parsed_actions = []
|
parsed_actions = []
|
||||||
try:
|
try:
|
||||||
action = action_json.get("action", "no_action")
|
# 从新的actions结构中获取动作信息
|
||||||
reasoning = action_json.get("reason", "未提供原因")
|
actions_obj = action_json.get("actions", {})
|
||||||
action_data = {k: v for k, v in action_json.items() if k not in ["action", "reason"]}
|
|
||||||
|
# 处理actions字段可能是字典或列表的情况
|
||||||
|
if isinstance(actions_obj, dict):
|
||||||
|
action = actions_obj.get("action_type", "no_action")
|
||||||
|
reasoning = actions_obj.get("reason", "未提供原因")
|
||||||
|
# 合并actions_obj中的其他字段作为action_data
|
||||||
|
action_data = {k: v for k, v in actions_obj.items() if k not in ["action_type", "reason"]}
|
||||||
|
elif isinstance(actions_obj, list) and actions_obj:
|
||||||
|
# 如果是列表,取第一个元素
|
||||||
|
first_action = actions_obj[0]
|
||||||
|
if isinstance(first_action, dict):
|
||||||
|
action = first_action.get("action_type", "no_action")
|
||||||
|
reasoning = first_action.get("reason", "未提供原因")
|
||||||
|
action_data = {k: v for k, v in first_action.items() if k not in ["action_type", "reason"]}
|
||||||
|
else:
|
||||||
|
action = "no_action"
|
||||||
|
reasoning = "actions格式错误"
|
||||||
|
action_data = {}
|
||||||
|
else:
|
||||||
|
action = "no_action"
|
||||||
|
reasoning = "actions格式错误"
|
||||||
|
action_data = {}
|
||||||
|
|
||||||
|
# 保留原始的thinking字段(如果有)
|
||||||
|
thinking = action_json.get("thinking")
|
||||||
|
if thinking:
|
||||||
|
action_data["thinking"] = thinking
|
||||||
|
|
||||||
target_message_obj = None
|
target_message_obj = None
|
||||||
if action not in ["no_action", "no_reply", "do_nothing", "proactive_reply"]:
|
if action not in ["no_action", "no_reply", "do_nothing", "proactive_reply"]:
|
||||||
if target_message_id := action_json.get("target_message_id"):
|
if target_message_id := action_data.get("target_message_id"):
|
||||||
target_message_dict = self._find_message_by_id(target_message_id, message_id_list)
|
target_message_dict = self._find_message_by_id(target_message_id, message_id_list)
|
||||||
else:
|
else:
|
||||||
# 如果LLM没有指定target_message_id,我们就默认选择最新的一条消息
|
# 如果LLM没有指定target_message_id,我们就默认选择最新的一条消息
|
||||||
@@ -388,7 +435,7 @@ class ChatterPlanFilter:
|
|||||||
# 如果找不到目标消息,对于reply动作来说这是必需的,应该记录警告
|
# 如果找不到目标消息,对于reply动作来说这是必需的,应该记录警告
|
||||||
if action == "reply":
|
if action == "reply":
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"reply动作找不到目标消息,target_message_id: {action_json.get('target_message_id')}"
|
f"reply动作找不到目标消息,target_message_id: {action_data.get('target_message_id')}"
|
||||||
)
|
)
|
||||||
# 将reply动作改为no_action,避免后续执行时出错
|
# 将reply动作改为no_action,避免后续执行时出错
|
||||||
action = "no_action"
|
action = "no_action"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ from src.chat.utils.utils import get_chat_type_and_target_info
|
|||||||
from src.common.data_models.database_data_model import DatabaseMessages
|
from src.common.data_models.database_data_model import DatabaseMessages
|
||||||
from src.common.data_models.info_data_model import Plan, TargetPersonInfo
|
from src.common.data_models.info_data_model import Plan, TargetPersonInfo
|
||||||
from src.config.config import global_config
|
from src.config.config import global_config
|
||||||
from src.plugin_system.base.component_types import ActionActivationType, ActionInfo, ChatMode, ChatType, ComponentType
|
from src.plugin_system.base.component_types import ActionInfo, ChatMode, ChatType
|
||||||
from src.plugin_system.core.component_registry import component_registry
|
from src.plugin_system.core.component_registry import component_registry
|
||||||
|
|
||||||
|
|
||||||
@@ -66,6 +66,7 @@ class ChatterPlanGenerator:
|
|||||||
# 构建计划对象
|
# 构建计划对象
|
||||||
plan = Plan(
|
plan = Plan(
|
||||||
chat_id=self.chat_id,
|
chat_id=self.chat_id,
|
||||||
|
chat_type=chat_type,
|
||||||
mode=mode,
|
mode=mode,
|
||||||
target_info=target_info,
|
target_info=target_info,
|
||||||
available_actions=available_actions,
|
available_actions=available_actions,
|
||||||
@@ -74,7 +75,7 @@ class ChatterPlanGenerator:
|
|||||||
|
|
||||||
return plan
|
return plan
|
||||||
|
|
||||||
except Exception as e:
|
except Exception:
|
||||||
# 如果生成失败,返回一个基本的空计划
|
# 如果生成失败,返回一个基本的空计划
|
||||||
return Plan(
|
return Plan(
|
||||||
chat_id=self.chat_id,
|
chat_id=self.chat_id,
|
||||||
@@ -110,7 +111,7 @@ class ChatterPlanGenerator:
|
|||||||
|
|
||||||
return filtered_actions
|
return filtered_actions
|
||||||
|
|
||||||
except Exception as e:
|
except Exception:
|
||||||
# 如果获取失败,返回空字典
|
# 如果获取失败,返回空字典
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@@ -124,9 +125,7 @@ class ChatterPlanGenerator:
|
|||||||
try:
|
try:
|
||||||
# 获取最近的消息记录
|
# 获取最近的消息记录
|
||||||
raw_messages = get_raw_msg_before_timestamp_with_chat(
|
raw_messages = get_raw_msg_before_timestamp_with_chat(
|
||||||
chat_id=self.chat_id,
|
chat_id=self.chat_id, timestamp=time.time(), limit=global_config.memory.short_memory_length
|
||||||
timestamp=time.time(),
|
|
||||||
limit=global_config.memory.short_memory_length
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 转换为 DatabaseMessages 对象
|
# 转换为 DatabaseMessages 对象
|
||||||
@@ -143,13 +142,13 @@ class ChatterPlanGenerator:
|
|||||||
user_platform=msg.get("user_platform", ""),
|
user_platform=msg.get("user_platform", ""),
|
||||||
)
|
)
|
||||||
recent_messages.append(db_msg)
|
recent_messages.append(db_msg)
|
||||||
except Exception as e:
|
except Exception:
|
||||||
# 跳过格式错误的消息
|
# 跳过格式错误的消息
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return recent_messages
|
return recent_messages
|
||||||
|
|
||||||
except Exception as e:
|
except Exception:
|
||||||
# 如果获取失败,返回空列表
|
# 如果获取失败,返回空列表
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@@ -162,6 +161,8 @@ class ChatterPlanGenerator:
|
|||||||
"""
|
"""
|
||||||
return {
|
return {
|
||||||
"chat_id": self.chat_id,
|
"chat_id": self.chat_id,
|
||||||
"action_count": len(self.action_manager._using_actions) if hasattr(self.action_manager, '_using_actions') else 0,
|
"action_count": len(self.action_manager._using_actions)
|
||||||
"generation_time": time.time()
|
if hasattr(self.action_manager, "_using_actions")
|
||||||
|
else 0,
|
||||||
|
"generation_time": time.time(),
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
|
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
from src.plugin_system.base.component_types import ChatMode
|
|
||||||
from src.plugins.built_in.affinity_flow_chatter.plan_executor import ChatterPlanExecutor
|
from src.plugins.built_in.affinity_flow_chatter.plan_executor import ChatterPlanExecutor
|
||||||
from src.plugins.built_in.affinity_flow_chatter.plan_filter import ChatterPlanFilter
|
from src.plugins.built_in.affinity_flow_chatter.plan_filter import ChatterPlanFilter
|
||||||
from src.plugins.built_in.affinity_flow_chatter.plan_generator import ChatterPlanGenerator
|
from src.plugins.built_in.affinity_flow_chatter.plan_generator import ChatterPlanGenerator
|
||||||
@@ -58,7 +57,6 @@ class ChatterActionPlanner:
|
|||||||
|
|
||||||
# 创建新的关系追踪器
|
# 创建新的关系追踪器
|
||||||
self.relationship_tracker = ChatterRelationshipTracker(self.interest_scoring)
|
self.relationship_tracker = ChatterRelationshipTracker(self.interest_scoring)
|
||||||
logger.info("创建新的关系追踪器实例")
|
|
||||||
|
|
||||||
# 设置执行器的关系追踪器
|
# 设置执行器的关系追踪器
|
||||||
self.executor.set_relationship_tracker(self.relationship_tracker)
|
self.executor.set_relationship_tracker(self.relationship_tracker)
|
||||||
@@ -72,14 +70,11 @@ class ChatterActionPlanner:
|
|||||||
"other_actions_executed": 0,
|
"other_actions_executed": 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
async def plan(
|
async def plan(self, context: "StreamContext" = None) -> Tuple[List[Dict], Optional[Dict]]:
|
||||||
self, mode: ChatMode = ChatMode.GROUP, context: "StreamContext" = None
|
|
||||||
) -> Tuple[List[Dict], Optional[Dict]]:
|
|
||||||
"""
|
"""
|
||||||
执行完整的增强版规划流程。
|
执行完整的增强版规划流程。
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
mode (ChatMode): 当前的聊天模式,默认为 GROUP。
|
|
||||||
context (StreamContext): 包含聊天流消息的上下文对象。
|
context (StreamContext): 包含聊天流消息的上下文对象。
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -90,18 +85,18 @@ class ChatterActionPlanner:
|
|||||||
try:
|
try:
|
||||||
self.planner_stats["total_plans"] += 1
|
self.planner_stats["total_plans"] += 1
|
||||||
|
|
||||||
return await self._enhanced_plan_flow(mode, context)
|
return await self._enhanced_plan_flow(context)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"规划流程出错: {e}")
|
logger.error(f"规划流程出错: {e}")
|
||||||
self.planner_stats["failed_plans"] += 1
|
self.planner_stats["failed_plans"] += 1
|
||||||
return [], None
|
return [], None
|
||||||
|
|
||||||
async def _enhanced_plan_flow(self, mode: ChatMode, context: "StreamContext") -> Tuple[List[Dict], Optional[Dict]]:
|
async def _enhanced_plan_flow(self, context: "StreamContext") -> Tuple[List[Dict], Optional[Dict]]:
|
||||||
"""执行增强版规划流程"""
|
"""执行增强版规划流程"""
|
||||||
try:
|
try:
|
||||||
# 1. 生成初始 Plan
|
# 1. 生成初始 Plan
|
||||||
initial_plan = await self.generator.generate(mode)
|
initial_plan = await self.generator.generate(context.chat_mode)
|
||||||
|
|
||||||
unread_messages = context.get_unread_messages() if context else []
|
unread_messages = context.get_unread_messages() if context else []
|
||||||
# 2. 兴趣度评分 - 只对未读消息进行评分
|
# 2. 兴趣度评分 - 只对未读消息进行评分
|
||||||
@@ -119,16 +114,14 @@ class ChatterActionPlanner:
|
|||||||
|
|
||||||
reply_not_available = False
|
reply_not_available = False
|
||||||
if not should_reply and "reply" in initial_plan.available_actions:
|
if not should_reply and "reply" in initial_plan.available_actions:
|
||||||
logger.info(f"兴趣度不足 ({latest_score.total_score:.2f}),移除'回复'动作。")
|
logger.info(f"兴趣度不足 ({latest_score.total_score:.2f}),移除回复")
|
||||||
reply_not_available = True
|
reply_not_available = True
|
||||||
|
|
||||||
# base_threshold = self.interest_scoring.reply_threshold
|
# base_threshold = self.interest_scoring.reply_threshold
|
||||||
# 检查兴趣度是否达到非回复动作阈值
|
# 检查兴趣度是否达到非回复动作阈值
|
||||||
non_reply_action_interest_threshold = global_config.affinity_flow.non_reply_action_interest_threshold
|
non_reply_action_interest_threshold = global_config.affinity_flow.non_reply_action_interest_threshold
|
||||||
if score < non_reply_action_interest_threshold:
|
if score < non_reply_action_interest_threshold:
|
||||||
logger.info(
|
logger.info(f"兴趣度 {score:.3f} 低于阈值 {non_reply_action_interest_threshold:.3f},不执行动作")
|
||||||
f"兴趣度 {score:.3f} 低于非回复动作阈值 {non_reply_action_interest_threshold:.3f},不执行任何动作。"
|
|
||||||
)
|
|
||||||
# 直接返回 no_action
|
# 直接返回 no_action
|
||||||
from src.common.data_models.info_data_model import ActionPlannerInfo
|
from src.common.data_models.info_data_model import ActionPlannerInfo
|
||||||
|
|
||||||
|
|||||||
@@ -49,10 +49,6 @@ def init_prompts():
|
|||||||
6. 如果需要,选择一个最合适的辅助动作与 `reply`(如果有) 组合。
|
6. 如果需要,选择一个最合适的辅助动作与 `reply`(如果有) 组合。
|
||||||
7. 如果用户明确要求了某个动作,请务必优先满足。
|
7. 如果用户明确要求了某个动作,请务必优先满足。
|
||||||
|
|
||||||
**动作限制:**
|
|
||||||
- 在私聊中,你只能使用 `reply` 动作。私聊中不允许使用任何其他动作。
|
|
||||||
- 在群聊中,你可以自由选择是否使用辅助动作。
|
|
||||||
|
|
||||||
**重要提醒:**
|
**重要提醒:**
|
||||||
- **回复消息时必须遵循对话的流程,不要重复已经说过的话。**
|
- **回复消息时必须遵循对话的流程,不要重复已经说过的话。**
|
||||||
- **确保回复与上下文紧密相关,回应要针对用户的消息内容。**
|
- **确保回复与上下文紧密相关,回应要针对用户的消息内容。**
|
||||||
@@ -62,7 +58,7 @@ def init_prompts():
|
|||||||
请严格按照以下 JSON 格式输出,包含 `thinking` 和 `actions` 字段:
|
请严格按照以下 JSON 格式输出,包含 `thinking` 和 `actions` 字段:
|
||||||
```json
|
```json
|
||||||
{{
|
{{
|
||||||
"thinking": "你的思考过程,分析当前情况并说明为什么选择这些动作",
|
"thinking": "你的内心思考,简要描述你选择动作时的心路历程",
|
||||||
"actions": [
|
"actions": [
|
||||||
{{
|
{{
|
||||||
"action_type": "动作类型(如:reply, emoji等)",
|
"action_type": "动作类型(如:reply, emoji等)",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from typing import List, Tuple, Type
|
|||||||
|
|
||||||
from src.plugin_system.apis.plugin_register_api import register_plugin
|
from src.plugin_system.apis.plugin_register_api import register_plugin
|
||||||
from src.plugin_system.base.base_plugin import BasePlugin
|
from src.plugin_system.base.base_plugin import BasePlugin
|
||||||
from src.plugin_system.base.component_types import ComponentInfo, ChatterInfo, ComponentType, ChatType
|
from src.plugin_system.base.component_types import ComponentInfo
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
|
|
||||||
logger = get_logger("affinity_chatter_plugin")
|
logger = get_logger("affinity_chatter_plugin")
|
||||||
|
|||||||
@@ -385,7 +385,9 @@ class ChatterRelationshipTracker:
|
|||||||
time_diff = reply_timestamp - last_tracked_time
|
time_diff = reply_timestamp - last_tracked_time
|
||||||
|
|
||||||
if time_diff < 5 * 60: # 5分钟内不重复追踪
|
if time_diff < 5 * 60: # 5分钟内不重复追踪
|
||||||
logger.debug(f"⏱️ [RelationshipTracker] 用户 {user_id} 距离上次追踪时间不足5分钟 ({time_diff:.2f}s),跳过")
|
logger.debug(
|
||||||
|
f"⏱️ [RelationshipTracker] 用户 {user_id} 距离上次追踪时间不足5分钟 ({time_diff:.2f}s),跳过"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# 获取上次bot回复该用户的消息
|
# 获取上次bot回复该用户的消息
|
||||||
@@ -647,6 +649,7 @@ class ChatterRelationshipTracker:
|
|||||||
|
|
||||||
# 获取bot人设信息
|
# 获取bot人设信息
|
||||||
from src.individuality.individuality import Individuality
|
from src.individuality.individuality import Individuality
|
||||||
|
|
||||||
individuality = Individuality()
|
individuality = Individuality()
|
||||||
bot_personality = await individuality.get_personality_block()
|
bot_personality = await individuality.get_personality_block()
|
||||||
|
|
||||||
@@ -682,11 +685,18 @@ class ChatterRelationshipTracker:
|
|||||||
return
|
return
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
cleaned_response = self._clean_llm_json_response(llm_response)
|
cleaned_response = self._clean_llm_json_response(llm_response)
|
||||||
response_data = json.loads(cleaned_response)
|
response_data = json.loads(cleaned_response)
|
||||||
|
|
||||||
new_text = response_data.get("relationship_text", "初次见面")
|
new_text = response_data.get("relationship_text", "初次见面")
|
||||||
new_score = max(0.0, min(1.0, float(response_data.get("relationship_score", global_config.affinity_flow.base_relationship_score))))
|
new_score = max(
|
||||||
|
0.0,
|
||||||
|
min(
|
||||||
|
1.0,
|
||||||
|
float(response_data.get("relationship_score", global_config.affinity_flow.base_relationship_score)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
# 更新数据库和缓存
|
# 更新数据库和缓存
|
||||||
self._update_user_relationship_in_db(user_id, new_text, new_score)
|
self._update_user_relationship_in_db(user_id, new_text, new_score)
|
||||||
@@ -702,7 +712,6 @@ class ChatterRelationshipTracker:
|
|||||||
logger.error(f"处理初次交互失败: {user_id}, 错误: {e}")
|
logger.error(f"处理初次交互失败: {user_id}, 错误: {e}")
|
||||||
logger.debug("错误详情:", exc_info=True)
|
logger.debug("错误详情:", exc_info=True)
|
||||||
|
|
||||||
|
|
||||||
def _clean_llm_json_response(self, response: str) -> str:
|
def _clean_llm_json_response(self, response: str) -> str:
|
||||||
"""
|
"""
|
||||||
清理LLM响应,移除可能的JSON格式标记
|
清理LLM响应,移除可能的JSON格式标记
|
||||||
|
|||||||
Reference in New Issue
Block a user