feat(affinity-flow): 重构亲和流配置系统

将硬编码的兴趣度评分参数迁移到集中式配置管理,新增AffinityFlowConfig配置类
- 从全局配置加载评分权重、阈值和计算参数
- 统一管理匹配奖励、关系分数和提及bot相关配置
- 更新配置文件模板包含完整的亲和流参数
- 确保各模块使用一致的配置值而非硬编码常量
This commit is contained in:
Windpicker-owo
2025-09-19 13:16:45 +08:00
parent 69f2ee64d9
commit e62843ea58
7 changed files with 113 additions and 40 deletions

View File

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

View File

@@ -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分析并更新关系

View File

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

View File

@@ -112,8 +112,9 @@ def init_prompt():
*你正在一个{chat_context_type}里聊天,你需要理解整个{chat_context_type}的聊天动态和话题走向,并做出自然的回应。*
### 核心任务
- 你现在的主要任务是和 {sender_name} 聊天。
- {reply_target_block} ,你需要生成一段紧密相关且能推动对话的回复。
- 你现在的主要任务是和 {sender_name} 聊天。{relation_info_block}同时,也有其他用户会参与聊天,你可以参考他们的回复内容,但是你现在想回复{sender_name}的发言。
- {reply_target_block} 你需要生成一段紧密相关且能推动对话的回复。
## 规则
{safety_guidelines_block}
@@ -202,6 +203,10 @@ If you need to use the search tool, please directly call the function "lpmm_sear
{keywords_reaction_prompt}
请注意不要输出多余内容(包括前后缀冒号和引号at或 @等 )。只输出回复内容。
{moderation_prompt}
你的核心任务是针对 {reply_target_block} 中提到的内容,{relation_info_block}生成一段紧密相关且能推动对话的回复。你的回复应该:
1. 明确回应目标消息,而不是宽泛地评论。
2. 可以分享你的看法、提出相关问题,或者开个合适的玩笑。
3. 目的是让对话更有趣、更深入。
最终请输出一条简短、完整且口语化的回复。
现在,你说:
""",

View File

@@ -42,7 +42,8 @@ from src.config.official_configs import (
CrossContextConfig,
PermissionConfig,
CommandConfig,
PlanningSystemConfig
PlanningSystemConfig,
AffinityFlowConfig
)
from .api_ada_configs import (
@@ -431,6 +432,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):

View File

@@ -703,3 +703,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="基础人物关系分")

View File

@@ -1,5 +1,5 @@
[inner]
version = "6.8.9"
version = "6.9.6"
#----以下是给开发人员阅读的如果你只是部署了MoFox-Bot不需要阅读----
#如果你想要修改配置文件请递增version的值
@@ -546,4 +546,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 # 基础人物关系分