feat(affinity-flow): 重构亲和流配置系统
将硬编码的兴趣度评分参数迁移到集中式配置管理,新增AffinityFlowConfig配置类 - 从全局配置加载评分权重、阈值和计算参数 - 统一管理匹配奖励、关系分数和提及bot相关配置 - 更新配置文件模板包含完整的亲和流参数 - 确保各模块使用一致的配置值而非硬编码常量
This commit is contained in:
@@ -23,21 +23,22 @@ class InterestScoringSystem:
|
||||
# 智能兴趣匹配配置
|
||||
self.use_smart_matching = True
|
||||
|
||||
# 评分权重
|
||||
# 从配置加载评分权重
|
||||
affinity_config = global_config.affinity_flow
|
||||
self.score_weights = {
|
||||
"interest_match": 0.5, # 兴趣匹配度权重
|
||||
"relationship": 0.3, # 关系分权重
|
||||
"mentioned": 0.2, # 是否提及bot权重
|
||||
"interest_match": affinity_config.keyword_match_weight, # 兴趣匹配度权重
|
||||
"relationship": affinity_config.relationship_weight, # 关系分权重
|
||||
"mentioned": affinity_config.mention_bot_weight, # 是否提及bot权重
|
||||
}
|
||||
|
||||
# 评分阈值
|
||||
self.reply_threshold = 0.62 # 默认回复阈值
|
||||
self.mention_threshold = 0.3 # 提及阈值
|
||||
self.reply_threshold = affinity_config.reply_action_interest_threshold # 回复动作兴趣阈值
|
||||
self.mention_threshold = affinity_config.mention_bot_adjustment_threshold # 提及bot后的调整阈值
|
||||
|
||||
# 连续不回复概率提升
|
||||
self.no_reply_count = 0
|
||||
self.max_no_reply_count = 10
|
||||
self.probability_boost_per_no_reply = 0.01 # 每次不回复增加5%概率
|
||||
self.max_no_reply_count = affinity_config.max_no_reply_count
|
||||
self.probability_boost_per_no_reply = affinity_config.no_reply_threshold_adjustment / affinity_config.max_no_reply_count # 每次不回复增加的概率
|
||||
|
||||
# 用户关系数据
|
||||
self.user_relationships: Dict[str, float] = {} # user_id -> relationship_score
|
||||
@@ -151,7 +152,8 @@ class InterestScoringSystem:
|
||||
logger.debug(f" 🔢 匹配详情: {match_result.match_scores}")
|
||||
|
||||
# 返回匹配分数,考虑置信度和匹配标签数量
|
||||
match_count_bonus = min(len(match_result.matched_tags) * 0.05, 0.3) # 每多匹配一个标签+0.05,最高+0.3
|
||||
affinity_config = global_config.affinity_flow
|
||||
match_count_bonus = min(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
|
||||
logger.debug(
|
||||
f"⚖️ 最终分数计算: 总分({match_result.overall_score:.3f}) × 1.3 × 置信度({match_result.confidence:.3f}) + 标签数量奖励({match_count_bonus:.3f}) = {final_score:.3f}"
|
||||
@@ -254,7 +256,7 @@ class InterestScoringSystem:
|
||||
logger.warning(f"从全局关系追踪器获取关系分失败: {e}")
|
||||
|
||||
# 默认新用户的基础分
|
||||
return 0.3
|
||||
return global_config.affinity_flow.base_relationship_score
|
||||
|
||||
def _calculate_mentioned_score(self, msg: DatabaseMessages, bot_nickname: str) -> float:
|
||||
"""计算提及分数"""
|
||||
@@ -262,7 +264,7 @@ class InterestScoringSystem:
|
||||
return 0.0
|
||||
|
||||
if msg.is_mentioned or (bot_nickname and bot_nickname in msg.processed_plain_text):
|
||||
return 1.0
|
||||
return global_config.affinity_flow.mention_bot_interest_score
|
||||
|
||||
return 0.0
|
||||
|
||||
@@ -280,7 +282,7 @@ class InterestScoringSystem:
|
||||
logger.debug(f"📋 基础阈值: {base_threshold:.3f}")
|
||||
|
||||
# 如果被提及,降低阈值
|
||||
if score.mentioned_score >= 1.0:
|
||||
if score.mentioned_score >= global_config.affinity_flow.mention_bot_interest_score * 0.5: # 使用提及bot兴趣分的一半作为判断阈值
|
||||
base_threshold = self.mention_threshold
|
||||
logger.debug(f"📣 消息提及了机器人,使用降低阈值: {base_threshold:.3f}")
|
||||
|
||||
@@ -308,7 +310,7 @@ class InterestScoringSystem:
|
||||
old_count = self.no_reply_count
|
||||
|
||||
if did_reply:
|
||||
self.no_reply_count = max(0, self.no_reply_count - 3)
|
||||
self.no_reply_count = max(0, self.no_reply_count - global_config.affinity_flow.reply_cooldown_reduction)
|
||||
action = "✅ reply动作可用"
|
||||
else:
|
||||
self.no_reply_count += 1
|
||||
@@ -323,7 +325,7 @@ class InterestScoringSystem:
|
||||
|
||||
def update_user_relationship(self, user_id: str, relationship_change: float):
|
||||
"""更新用户关系"""
|
||||
old_score = self.user_relationships.get(user_id, 0.3) # 默认新用户分数
|
||||
old_score = self.user_relationships.get(user_id, global_config.affinity_flow.base_relationship_score) # 默认新用户分数
|
||||
new_score = max(0.0, min(1.0, old_score + relationship_change))
|
||||
|
||||
self.user_relationships[user_id] = new_score
|
||||
|
||||
@@ -8,7 +8,7 @@ import time
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.config.config import model_config
|
||||
from src.config.config import model_config, global_config
|
||||
from src.llm_models.utils_model import LLMRequest
|
||||
from src.common.database.sqlalchemy_database_api import get_db_session
|
||||
from src.common.database.sqlalchemy_models import UserRelationships, Messages
|
||||
@@ -79,7 +79,7 @@ class UserRelationshipTracker:
|
||||
del self.tracking_users[oldest_user]
|
||||
|
||||
# 获取当前关系分
|
||||
current_relationship_score = 0.3 # 默认值
|
||||
current_relationship_score = global_config.affinity_flow.base_relationship_score # 默认值
|
||||
if self.interest_scoring_system:
|
||||
current_relationship_score = self.interest_scoring_system.get_user_relationship(user_id)
|
||||
|
||||
@@ -139,7 +139,7 @@ Bot回复: {interaction["bot_reply"]}
|
||||
# 清理LLM响应,移除可能的格式标记
|
||||
cleaned_response = self._clean_llm_json_response(llm_response)
|
||||
response_data = json.loads(cleaned_response)
|
||||
new_score = max(0.0, min(1.0, float(response_data.get("new_relationship_score", 0.3))))
|
||||
new_score = max(0.0, min(1.0, float(response_data.get("new_relationship_score", global_config.affinity_flow.base_relationship_score))))
|
||||
|
||||
if self.interest_scoring_system:
|
||||
self.interest_scoring_system.update_user_relationship(
|
||||
@@ -258,7 +258,7 @@ Bot回复: {interaction["bot_reply"]}
|
||||
# 检查缓存是否过期
|
||||
cache_time = cache_data.get("last_tracked", 0)
|
||||
if time.time() - cache_time < self.cache_expiry_hours * 3600:
|
||||
return cache_data.get("relationship_score", 0.3)
|
||||
return cache_data.get("relationship_score", global_config.affinity_flow.base_relationship_score)
|
||||
|
||||
# 缓存过期或不存在,从数据库获取
|
||||
relationship_data = self._get_user_relationship_from_db(user_id)
|
||||
@@ -266,13 +266,13 @@ Bot回复: {interaction["bot_reply"]}
|
||||
# 更新缓存
|
||||
self.user_relationship_cache[user_id] = {
|
||||
"relationship_text": relationship_data.get("relationship_text", ""),
|
||||
"relationship_score": relationship_data.get("relationship_score", 0.3),
|
||||
"relationship_score": relationship_data.get("relationship_score", global_config.affinity_flow.base_relationship_score),
|
||||
"last_tracked": time.time(),
|
||||
}
|
||||
return relationship_data.get("relationship_score", 0.3)
|
||||
return relationship_data.get("relationship_score", global_config.affinity_flow.base_relationship_score)
|
||||
|
||||
# 数据库中也没有,返回默认值
|
||||
return 0.3
|
||||
return global_config.affinity_flow.base_relationship_score
|
||||
|
||||
def _get_user_relationship_from_db(self, user_id: str) -> Optional[Dict]:
|
||||
"""从数据库获取用户关系数据"""
|
||||
@@ -357,7 +357,7 @@ Bot回复: {interaction["bot_reply"]}
|
||||
|
||||
# 获取当前关系数据
|
||||
current_relationship = self._get_user_relationship_from_db(user_id)
|
||||
current_score = current_relationship.get("relationship_score", 0.3) if current_relationship else 0.3
|
||||
current_score = current_relationship.get("relationship_score", global_config.affinity_flow.base_relationship_score) if current_relationship else global_config.affinity_flow.base_relationship_score
|
||||
current_text = current_relationship.get("relationship_text", "新用户") if current_relationship else "新用户"
|
||||
|
||||
# 使用LLM分析并更新关系
|
||||
|
||||
@@ -9,6 +9,7 @@ from datetime import datetime
|
||||
import numpy as np
|
||||
|
||||
from src.common.logger import get_logger
|
||||
from src.config.config import global_config
|
||||
from src.common.data_models.bot_interest_data_model import (
|
||||
BotPersonalityInterests, BotInterestTag, InterestMatchResult
|
||||
)
|
||||
@@ -433,9 +434,10 @@ class BotInterestManager:
|
||||
low_similarity_count = 0
|
||||
|
||||
# 分级相似度阈值
|
||||
high_threshold = 0.55
|
||||
medium_threshold = 0.47
|
||||
low_threshold = 0.3
|
||||
affinity_config = global_config.affinity_flow
|
||||
high_threshold = affinity_config.high_match_interest_threshold
|
||||
medium_threshold = affinity_config.medium_match_interest_threshold
|
||||
low_threshold = affinity_config.low_match_interest_threshold
|
||||
|
||||
logger.debug(f"🔍 使用分级相似度阈值: 高={high_threshold}, 中={medium_threshold}, 低={low_threshold}")
|
||||
|
||||
@@ -449,7 +451,7 @@ class BotInterestManager:
|
||||
# 根据相似度等级应用不同的加成
|
||||
if similarity > high_threshold:
|
||||
# 高相似度:强加成
|
||||
enhanced_score = weighted_score * 1.8
|
||||
enhanced_score = weighted_score * affinity_config.high_match_keyword_multiplier
|
||||
match_count += 1
|
||||
high_similarity_count += 1
|
||||
result.add_match(tag.tag_name, enhanced_score, [tag.tag_name])
|
||||
@@ -457,7 +459,7 @@ class BotInterestManager:
|
||||
|
||||
elif similarity > medium_threshold:
|
||||
# 中相似度:中等加成
|
||||
enhanced_score = weighted_score * 1.4
|
||||
enhanced_score = weighted_score * affinity_config.medium_match_keyword_multiplier
|
||||
match_count += 1
|
||||
medium_similarity_count += 1
|
||||
result.add_match(tag.tag_name, enhanced_score, [tag.tag_name])
|
||||
@@ -465,7 +467,7 @@ class BotInterestManager:
|
||||
|
||||
elif similarity > low_threshold:
|
||||
# 低相似度:轻微加成
|
||||
enhanced_score = weighted_score * 1.15
|
||||
enhanced_score = weighted_score * affinity_config.low_match_keyword_multiplier
|
||||
match_count += 1
|
||||
low_similarity_count += 1
|
||||
result.add_match(tag.tag_name, enhanced_score, [tag.tag_name])
|
||||
@@ -506,6 +508,7 @@ class BotInterestManager:
|
||||
if not keywords or not matched_tags:
|
||||
return {}
|
||||
|
||||
affinity_config = global_config.affinity_flow
|
||||
bonus_dict = {}
|
||||
|
||||
for tag_name in matched_tags:
|
||||
@@ -518,21 +521,21 @@ class BotInterestManager:
|
||||
|
||||
# 完全匹配
|
||||
if keyword_lower == tag_name_lower:
|
||||
bonus += 0.3
|
||||
logger.debug(f" 🎯 关键词完全匹配: '{keyword}' == '{tag_name}' (+0.3)")
|
||||
bonus += affinity_config.high_match_interest_threshold * 0.6 # 使用高匹配阈值的60%作为完全匹配奖励
|
||||
logger.debug(f" 🎯 关键词完全匹配: '{keyword}' == '{tag_name}' (+{affinity_config.high_match_interest_threshold * 0.6:.3f})")
|
||||
|
||||
# 包含匹配
|
||||
elif keyword_lower in tag_name_lower or tag_name_lower in keyword_lower:
|
||||
bonus += 0.15
|
||||
logger.debug(f" 🎯 关键词包含匹配: '{keyword}' ⊃ '{tag_name}' (+0.15)")
|
||||
bonus += affinity_config.medium_match_interest_threshold * 0.3 # 使用中匹配阈值的30%作为包含匹配奖励
|
||||
logger.debug(f" 🎯 关键词包含匹配: '{keyword}' ⊃ '{tag_name}' (+{affinity_config.medium_match_interest_threshold * 0.3:.3f})")
|
||||
|
||||
# 部分匹配(编辑距离)
|
||||
elif self._calculate_partial_match(keyword_lower, tag_name_lower):
|
||||
bonus += 0.08
|
||||
logger.debug(f" 🎯 关键词部分匹配: '{keyword}' ≈ '{tag_name}' (+0.08)")
|
||||
bonus += affinity_config.low_match_interest_threshold * 0.4 # 使用低匹配阈值的40%作为部分匹配奖励
|
||||
logger.debug(f" 🎯 关键词部分匹配: '{keyword}' ≈ '{tag_name}' (+{affinity_config.low_match_interest_threshold * 0.4:.3f})")
|
||||
|
||||
if bonus > 0:
|
||||
bonus_dict[tag_name] = min(bonus, 0.5) # 最大奖励限制为0.5
|
||||
bonus_dict[tag_name] = min(bonus, affinity_config.max_match_bonus) # 使用配置的最大奖励限制
|
||||
|
||||
return bonus_dict
|
||||
|
||||
|
||||
@@ -113,9 +113,9 @@ def init_prompt():
|
||||
*你正在一个QQ群里聊天,你需要理解整个群的聊天动态和话题走向,并做出自然的回应。*
|
||||
|
||||
### 核心任务
|
||||
- 你现在的主要任务是和 {sender_name} 聊天。同时,也有其他用户会参与聊天,你可以参考他们的回复内容,但是你现在想回复{sender_name}的发言。
|
||||
- 你现在的主要任务是和 {sender_name} 聊天。{relation_info_block}同时,也有其他用户会参与聊天,你可以参考他们的回复内容,但是你现在想回复{sender_name}的发言。
|
||||
|
||||
- {reply_target_block} ,你需要生成一段紧密相关且能推动对话的回复。
|
||||
- {reply_target_block} 你需要生成一段紧密相关且能推动对话的回复。
|
||||
|
||||
## 规则
|
||||
{safety_guidelines_block}
|
||||
@@ -207,7 +207,7 @@ If you need to use the search tool, please directly call the function "lpmm_sear
|
||||
{keywords_reaction_prompt}
|
||||
请注意不要输出多余内容(包括前后缀,冒号和引号,at或 @等 )。只输出回复内容。
|
||||
{moderation_prompt}
|
||||
你的核心任务是针对 {reply_target_block} 中提到的内容,生成一段紧密相关且能推动对话的回复。你的回复应该:
|
||||
你的核心任务是针对 {reply_target_block} 中提到的内容,{relation_info_block}生成一段紧密相关且能推动对话的回复。你的回复应该:
|
||||
1. 明确回应目标消息,而不是宽泛地评论。
|
||||
2. 可以分享你的看法、提出相关问题,或者开个合适的玩笑。
|
||||
3. 目的是让对话更有趣、更深入。
|
||||
|
||||
@@ -43,7 +43,8 @@ from src.config.official_configs import (
|
||||
CrossContextConfig,
|
||||
PermissionConfig,
|
||||
CommandConfig,
|
||||
PlanningSystemConfig
|
||||
PlanningSystemConfig,
|
||||
AffinityFlowConfig
|
||||
)
|
||||
|
||||
from .api_ada_configs import (
|
||||
@@ -398,6 +399,9 @@ class Config(ValidatedConfigBase):
|
||||
cross_context: CrossContextConfig = Field(
|
||||
default_factory=lambda: CrossContextConfig(), description="跨群聊上下文共享配置"
|
||||
)
|
||||
affinity_flow: AffinityFlowConfig = Field(
|
||||
default_factory=lambda: AffinityFlowConfig(), description="亲和流配置"
|
||||
)
|
||||
|
||||
|
||||
class APIAdapterConfig(ValidatedConfigBase):
|
||||
|
||||
@@ -670,3 +670,34 @@ class PermissionConfig(ValidatedConfigBase):
|
||||
master_users: List[List[str]] = Field(
|
||||
default_factory=list, description="Master用户列表,格式: [[platform, user_id], ...]"
|
||||
)
|
||||
|
||||
|
||||
class AffinityFlowConfig(ValidatedConfigBase):
|
||||
"""亲和流配置类(兴趣度评分和人物关系系统)"""
|
||||
|
||||
# 兴趣评分系统参数
|
||||
reply_action_interest_threshold: float = Field(default=0.4, description="回复动作兴趣阈值")
|
||||
non_reply_action_interest_threshold: float = Field(default=0.2, description="非回复动作兴趣阈值")
|
||||
high_match_interest_threshold: float = Field(default=0.8, description="高匹配兴趣阈值")
|
||||
medium_match_interest_threshold: float = Field(default=0.5, description="中匹配兴趣阈值")
|
||||
low_match_interest_threshold: float = Field(default=0.2, description="低匹配兴趣阈值")
|
||||
high_match_keyword_multiplier: float = Field(default=1.5, description="高匹配关键词兴趣倍率")
|
||||
medium_match_keyword_multiplier: float = Field(default=1.2, description="中匹配关键词兴趣倍率")
|
||||
low_match_keyword_multiplier: float = Field(default=1.0, description="低匹配关键词兴趣倍率")
|
||||
match_count_bonus: float = Field(default=0.1, description="匹配数关键词加成值")
|
||||
max_match_bonus: float = Field(default=0.5, description="最大匹配数加成值")
|
||||
|
||||
# 回复决策系统参数
|
||||
no_reply_threshold_adjustment: float = Field(default=0.1, description="不回复兴趣阈值调整值")
|
||||
reply_cooldown_reduction: int = Field(default=2, description="回复后减少的不回复计数")
|
||||
max_no_reply_count: int = Field(default=5, description="最大不回复计数次数")
|
||||
|
||||
# 综合评分权重
|
||||
keyword_match_weight: float = Field(default=0.4, description="兴趣关键词匹配度权重")
|
||||
mention_bot_weight: float = Field(default=0.3, description="提及bot分数权重")
|
||||
relationship_weight: float = Field(default=0.3, description="人物关系分数权重")
|
||||
|
||||
# 提及bot相关参数
|
||||
mention_bot_adjustment_threshold: float = Field(default=0.3, description="提及bot后的调整阈值")
|
||||
mention_bot_interest_score: float = Field(default=0.6, description="提及bot的兴趣分")
|
||||
base_relationship_score: float = Field(default=0.5, description="基础人物关系分")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[inner]
|
||||
version = "6.8.6"
|
||||
version = "6.9.6"
|
||||
|
||||
#----以下是给开发人员阅读的,如果你只是部署了MoFox-Bot,不需要阅读----
|
||||
#如果你想要修改配置文件,请递增version的值
|
||||
@@ -520,4 +520,32 @@ name = "Maizone默认互通组"
|
||||
chat_ids = [
|
||||
["group", "111111"], # 示例群聊1
|
||||
["private", "222222"] # 示例私聊2
|
||||
]
|
||||
]
|
||||
|
||||
[affinity_flow]
|
||||
# 兴趣评分系统参数
|
||||
reply_action_interest_threshold = 0.62 # 回复动作兴趣阈值
|
||||
non_reply_action_interest_threshold = 0.48 # 非回复动作兴趣阈值
|
||||
high_match_interest_threshold = 0.65 # 高匹配兴趣阈值
|
||||
medium_match_interest_threshold = 0.5 # 中匹配兴趣阈值
|
||||
low_match_interest_threshold = 0.2 # 低匹配兴趣阈值
|
||||
high_match_keyword_multiplier = 1.8 # 高匹配关键词兴趣倍率
|
||||
medium_match_keyword_multiplier = 1.4 # 中匹配关键词兴趣倍率
|
||||
low_match_keyword_multiplier = 1.15 # 低匹配关键词兴趣倍率
|
||||
match_count_bonus = 0.05 # 匹配数关键词加成值
|
||||
max_match_bonus = 0.3 # 最大匹配数加成值
|
||||
|
||||
# 回复决策系统参数
|
||||
no_reply_threshold_adjustment = 0.1 # 不回复兴趣阈值调整值
|
||||
reply_cooldown_reduction = 2 # 回复后减少的不回复计数
|
||||
max_no_reply_count = 5 # 最大不回复计数次数
|
||||
|
||||
# 综合评分权重
|
||||
keyword_match_weight = 0.4 # 兴趣关键词匹配度权重
|
||||
mention_bot_weight = 0.3 # 提及bot分数权重
|
||||
relationship_weight = 0.3 # 人物关系分数权重
|
||||
|
||||
# 提及bot相关参数
|
||||
mention_bot_adjustment_threshold = 0.3 # 提及bot后的调整阈值
|
||||
mention_bot_interest_score = 0.6 # 提及bot的兴趣分
|
||||
base_relationship_score = 0.3 # 基础人物关系分
|
||||
Reference in New Issue
Block a user