remove & fix:移除人格表达,修复过滤词失效,私聊强制focus
This commit is contained in:
@@ -80,14 +80,16 @@ class ExpressionSelector:
|
||||
)
|
||||
|
||||
def get_random_expressions(
|
||||
self, chat_id: str, style_num: int, grammar_num: int, personality_num: int
|
||||
self, chat_id: str, total_num: int, style_percentage: float, grammar_percentage: float
|
||||
) -> Tuple[List[Dict[str, str]], List[Dict[str, str]]]:
|
||||
(
|
||||
learnt_style_expressions,
|
||||
learnt_grammar_expressions,
|
||||
personality_expressions,
|
||||
) = self.expression_learner.get_expression_by_chat_id(chat_id)
|
||||
|
||||
style_num = int(total_num * style_percentage)
|
||||
grammar_num = int(total_num * grammar_percentage)
|
||||
|
||||
# 按权重抽样(使用count作为权重)
|
||||
if learnt_style_expressions:
|
||||
style_weights = [expr.get("count", 1) for expr in learnt_style_expressions]
|
||||
@@ -101,13 +103,7 @@ class ExpressionSelector:
|
||||
else:
|
||||
selected_grammar = []
|
||||
|
||||
if personality_expressions:
|
||||
personality_weights = [expr.get("count", 1) for expr in personality_expressions]
|
||||
selected_personality = weighted_sample(personality_expressions, personality_weights, personality_num)
|
||||
else:
|
||||
selected_personality = []
|
||||
|
||||
return selected_style, selected_grammar, selected_personality
|
||||
return selected_style, selected_grammar
|
||||
|
||||
def update_expressions_count_batch(self, expressions_to_update: List[Dict[str, str]], increment: float = 0.1):
|
||||
"""对一批表达方式更新count值,按文件分组后一次性写入"""
|
||||
@@ -174,7 +170,7 @@ class ExpressionSelector:
|
||||
"""使用LLM选择适合的表达方式"""
|
||||
|
||||
# 1. 获取35个随机表达方式(现在按权重抽取)
|
||||
style_exprs, grammar_exprs, personality_exprs = self.get_random_expressions(chat_id, 25, 25, 10)
|
||||
style_exprs, grammar_exprs= self.get_random_expressions(chat_id, 50, 0.5, 0.5)
|
||||
|
||||
# 2. 构建所有表达方式的索引和情境列表
|
||||
all_expressions = []
|
||||
@@ -196,13 +192,6 @@ class ExpressionSelector:
|
||||
all_expressions.append(expr_with_type)
|
||||
all_situations.append(f"{len(all_expressions)}.{expr['situation']}")
|
||||
|
||||
# 添加personality表达方式
|
||||
for expr in personality_exprs:
|
||||
if isinstance(expr, dict) and "situation" in expr and "style" in expr:
|
||||
expr_with_type = expr.copy()
|
||||
expr_with_type["type"] = "style_personality"
|
||||
all_expressions.append(expr_with_type)
|
||||
all_situations.append(f"{len(all_expressions)}.{expr['situation']}")
|
||||
|
||||
if not all_expressions:
|
||||
logger.warning("没有找到可用的表达方式")
|
||||
@@ -260,7 +249,7 @@ class ExpressionSelector:
|
||||
|
||||
# 对选中的所有表达方式,一次性更新count数
|
||||
if valid_expressions:
|
||||
self.update_expressions_count_batch(valid_expressions, 0.003)
|
||||
self.update_expressions_count_batch(valid_expressions, 0.006)
|
||||
|
||||
# logger.info(f"LLM从{len(all_expressions)}个情境中选择了{len(valid_expressions)}个")
|
||||
return valid_expressions
|
||||
|
||||
@@ -76,14 +76,13 @@ class ExpressionLearner:
|
||||
|
||||
def get_expression_by_chat_id(
|
||||
self, chat_id: str
|
||||
) -> Tuple[List[Dict[str, str]], List[Dict[str, str]], List[Dict[str, str]]]:
|
||||
) -> Tuple[List[Dict[str, str]], List[Dict[str, str]]]:
|
||||
"""
|
||||
获取指定chat_id的style和grammar表达方式, 同时获取全局的personality表达方式
|
||||
获取指定chat_id的style和grammar表达方式
|
||||
返回的每个表达方式字典中都包含了source_id, 用于后续的更新操作
|
||||
"""
|
||||
learnt_style_expressions = []
|
||||
learnt_grammar_expressions = []
|
||||
personality_expressions = []
|
||||
|
||||
# 获取style表达方式
|
||||
style_dir = os.path.join("data", "expression", "learnt_style", str(chat_id))
|
||||
@@ -111,19 +110,8 @@ class ExpressionLearner:
|
||||
except Exception as e:
|
||||
logger.error(f"读取grammar表达方式失败: {e}")
|
||||
|
||||
# 获取personality表达方式
|
||||
personality_file = os.path.join("data", "expression", "personality", "expressions.json")
|
||||
if os.path.exists(personality_file):
|
||||
try:
|
||||
with open(personality_file, "r", encoding="utf-8") as f:
|
||||
expressions = json.load(f)
|
||||
for expr in expressions:
|
||||
expr["source_id"] = "personality" # 添加来源ID
|
||||
personality_expressions.append(expr)
|
||||
except Exception as e:
|
||||
logger.error(f"读取personality表达方式失败: {e}")
|
||||
|
||||
return learnt_style_expressions, learnt_grammar_expressions, personality_expressions
|
||||
return learnt_style_expressions, learnt_grammar_expressions
|
||||
|
||||
def is_similar(self, s1: str, s2: str) -> bool:
|
||||
"""
|
||||
@@ -428,11 +416,12 @@ class ExpressionLearner:
|
||||
|
||||
init_prompt()
|
||||
|
||||
expression_learner = None
|
||||
|
||||
if global_config.expression.enable_expression:
|
||||
expression_learner = None
|
||||
|
||||
def get_expression_learner():
|
||||
global expression_learner
|
||||
if expression_learner is None:
|
||||
expression_learner = ExpressionLearner()
|
||||
return expression_learner
|
||||
def get_expression_learner():
|
||||
global expression_learner
|
||||
if expression_learner is None:
|
||||
expression_learner = ExpressionLearner()
|
||||
return expression_learner
|
||||
|
||||
@@ -3,16 +3,14 @@ from src.config.config import global_config
|
||||
from src.chat.message_receive.message import MessageRecv
|
||||
from src.chat.message_receive.storage import MessageStorage
|
||||
from src.chat.heart_flow.heartflow import heartflow
|
||||
from src.chat.message_receive.chat_stream import get_chat_manager, ChatStream
|
||||
from src.chat.message_receive.chat_stream import get_chat_manager
|
||||
from src.chat.utils.utils import is_mentioned_bot_in_message
|
||||
from src.chat.utils.timer_calculator import Timer
|
||||
from src.common.logger import get_logger
|
||||
|
||||
import math
|
||||
import re
|
||||
import math
|
||||
import traceback
|
||||
from typing import Optional, Tuple
|
||||
from maim_message import UserInfo
|
||||
|
||||
from src.person_info.relationship_manager import get_relationship_manager
|
||||
|
||||
@@ -90,44 +88,7 @@ async def _calculate_interest(message: MessageRecv) -> Tuple[float, bool]:
|
||||
return interested_rate, is_mentioned
|
||||
|
||||
|
||||
def _check_ban_words(text: str, chat: ChatStream, userinfo: UserInfo) -> bool:
|
||||
"""检查消息是否包含过滤词
|
||||
|
||||
Args:
|
||||
text: 待检查的文本
|
||||
chat: 聊天对象
|
||||
userinfo: 用户信息
|
||||
|
||||
Returns:
|
||||
bool: 是否包含过滤词
|
||||
"""
|
||||
for word in global_config.message_receive.ban_words:
|
||||
if word in text:
|
||||
chat_name = chat.group_info.group_name if chat.group_info else "私聊"
|
||||
logger.info(f"[{chat_name}]{userinfo.user_nickname}:{text}")
|
||||
logger.info(f"[过滤词识别]消息中含有{word},filtered")
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _check_ban_regex(text: str, chat: ChatStream, userinfo: UserInfo) -> bool:
|
||||
"""检查消息是否匹配过滤正则表达式
|
||||
|
||||
Args:
|
||||
text: 待检查的文本
|
||||
chat: 聊天对象
|
||||
userinfo: 用户信息
|
||||
|
||||
Returns:
|
||||
bool: 是否匹配过滤正则
|
||||
"""
|
||||
for pattern in global_config.message_receive.ban_msgs_regex:
|
||||
if re.search(pattern, text):
|
||||
chat_name = chat.group_info.group_name if chat.group_info else "私聊"
|
||||
logger.info(f"[{chat_name}]{userinfo.user_nickname}:{text}")
|
||||
logger.info(f"[正则表达式过滤]消息匹配到{pattern},filtered")
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class HeartFCMessageReceiver:
|
||||
@@ -167,12 +128,6 @@ class HeartFCMessageReceiver:
|
||||
subheartflow = await heartflow.get_or_create_subheartflow(chat.stream_id)
|
||||
message.update_chat_stream(chat)
|
||||
|
||||
# 3. 过滤检查
|
||||
if _check_ban_words(message.processed_plain_text, chat, userinfo) or _check_ban_regex(
|
||||
message.raw_message, chat, userinfo
|
||||
):
|
||||
return
|
||||
|
||||
# 6. 兴趣度计算与更新
|
||||
interested_rate, is_mentioned = await _calculate_interest(message)
|
||||
subheartflow.add_message_to_normal_chat_cache(message, interested_rate, is_mentioned)
|
||||
@@ -183,7 +138,6 @@ class HeartFCMessageReceiver:
|
||||
current_talk_frequency = global_config.chat.get_current_talk_frequency(chat.stream_id)
|
||||
|
||||
# 如果消息中包含图片标识,则日志展示为图片
|
||||
import re
|
||||
|
||||
picid_match = re.search(r"\[picid:([^\]]+)\]", message.processed_plain_text)
|
||||
if picid_match:
|
||||
|
||||
@@ -62,7 +62,10 @@ class SubHeartflow:
|
||||
"""异步初始化方法,创建兴趣流并确定聊天类型"""
|
||||
|
||||
# 根据配置决定初始状态
|
||||
if global_config.chat.chat_mode == "focus":
|
||||
if not self.is_group_chat:
|
||||
logger.debug(f"{self.log_prefix} 检测到是私聊,将直接尝试进入 FOCUSED 状态。")
|
||||
await self.change_chat_state(ChatState.FOCUSED)
|
||||
elif global_config.chat.chat_mode == "focus":
|
||||
logger.debug(f"{self.log_prefix} 配置为 focus 模式,将直接尝试进入 FOCUSED 状态。")
|
||||
await self.change_chat_state(ChatState.FOCUSED)
|
||||
else: # "auto" 或其他模式保持原有逻辑或默认为 NORMAL
|
||||
|
||||
@@ -91,16 +91,10 @@ class SubHeartflowManager:
|
||||
return subflow
|
||||
|
||||
try:
|
||||
# 初始化子心流, 传入 mai_state_info
|
||||
new_subflow = SubHeartflow(
|
||||
subheartflow_id,
|
||||
)
|
||||
|
||||
# 首先创建并添加聊天观察者
|
||||
# observation = ChattingObservation(chat_id=subheartflow_id)
|
||||
# await observation.initialize()
|
||||
# new_subflow.add_observation(observation)
|
||||
|
||||
# 然后再进行异步初始化,此时 SubHeartflow 内部若需启动 HeartFChatting,就能拿到 observation
|
||||
await new_subflow.initialize()
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@ from src.config.config import global_config
|
||||
from src.plugin_system.core.component_registry import component_registry # 导入新插件系统
|
||||
from src.plugin_system.base.base_command import BaseCommand
|
||||
from src.mais4u.mais4u_chat.s4u_msg_processor import S4UMessageProcessor
|
||||
from maim_message import UserInfo
|
||||
from src.chat.message_receive.chat_stream import ChatStream
|
||||
import re
|
||||
# 定义日志配置
|
||||
|
||||
# 获取项目根目录(假设本文件在src/chat/message_receive/下,根目录为上上上级目录)
|
||||
@@ -29,6 +32,44 @@ if ENABLE_S4U_CHAT:
|
||||
# 配置主程序日志格式
|
||||
logger = get_logger("chat")
|
||||
|
||||
def _check_ban_words(text: str, chat: ChatStream, userinfo: UserInfo) -> bool:
|
||||
"""检查消息是否包含过滤词
|
||||
|
||||
Args:
|
||||
text: 待检查的文本
|
||||
chat: 聊天对象
|
||||
userinfo: 用户信息
|
||||
|
||||
Returns:
|
||||
bool: 是否包含过滤词
|
||||
"""
|
||||
for word in global_config.message_receive.ban_words:
|
||||
if word in text:
|
||||
chat_name = chat.group_info.group_name if chat.group_info else "私聊"
|
||||
logger.info(f"[{chat_name}]{userinfo.user_nickname}:{text}")
|
||||
logger.info(f"[过滤词识别]消息中含有{word},filtered")
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _check_ban_regex(text: str, chat: ChatStream, userinfo: UserInfo) -> bool:
|
||||
"""检查消息是否匹配过滤正则表达式
|
||||
|
||||
Args:
|
||||
text: 待检查的文本
|
||||
chat: 聊天对象
|
||||
userinfo: 用户信息
|
||||
|
||||
Returns:
|
||||
bool: 是否匹配过滤正则
|
||||
"""
|
||||
for pattern in global_config.message_receive.ban_msgs_regex:
|
||||
if re.search(pattern, text):
|
||||
chat_name = chat.group_info.group_name if chat.group_info else "私聊"
|
||||
logger.info(f"[{chat_name}]{userinfo.user_nickname}:{text}")
|
||||
logger.info(f"[正则表达式过滤]消息匹配到{pattern},filtered")
|
||||
return True
|
||||
return False
|
||||
|
||||
class ChatBot:
|
||||
def __init__(self):
|
||||
@@ -49,17 +90,6 @@ class ChatBot:
|
||||
|
||||
self._started = True
|
||||
|
||||
async def _create_pfc_chat(self, message: MessageRecv):
|
||||
try:
|
||||
if global_config.experimental.pfc_chatting:
|
||||
chat_id = str(message.chat_stream.stream_id)
|
||||
private_name = str(message.message_info.user_info.user_nickname)
|
||||
|
||||
await self.pfc_manager.get_or_create_conversation(chat_id, private_name)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"创建PFC聊天失败: {e}")
|
||||
|
||||
async def _process_commands_with_new_system(self, message: MessageRecv):
|
||||
# sourcery skip: use-named-expression
|
||||
"""使用新插件系统处理命令"""
|
||||
@@ -149,14 +179,20 @@ class ChatBot:
|
||||
return
|
||||
|
||||
get_chat_manager().register_message(message)
|
||||
|
||||
# 创建聊天流
|
||||
|
||||
chat = await get_chat_manager().get_or_create_stream(
|
||||
platform=message.message_info.platform,
|
||||
user_info=user_info,
|
||||
group_info=group_info,
|
||||
)
|
||||
|
||||
message.update_chat_stream(chat)
|
||||
|
||||
# 过滤检查
|
||||
if _check_ban_words(message.processed_plain_text, chat, user_info) or _check_ban_regex(
|
||||
message.raw_message, chat, user_info
|
||||
):
|
||||
return
|
||||
|
||||
# 处理消息内容,生成纯文本
|
||||
await message.process()
|
||||
@@ -183,26 +219,12 @@ class ChatBot:
|
||||
template_group_name = None
|
||||
|
||||
async def preprocess():
|
||||
logger.debug("开始预处理消息...")
|
||||
# 如果在私聊中
|
||||
if group_info is None:
|
||||
logger.debug("检测到私聊消息")
|
||||
if ENABLE_S4U_CHAT:
|
||||
logger.debug("进入S4U私聊处理流程")
|
||||
await self.s4u_message_processor.process_message(message)
|
||||
return
|
||||
else:
|
||||
logger.debug("进入普通心流私聊处理")
|
||||
await self.heartflow_message_receiver.process_message(message)
|
||||
# 群聊默认进入心流消息处理逻辑
|
||||
else:
|
||||
if ENABLE_S4U_CHAT:
|
||||
logger.debug("进入S4U私聊处理流程")
|
||||
await self.s4u_message_processor.process_message(message)
|
||||
return
|
||||
else:
|
||||
logger.debug(f"检测到群聊消息,群ID: {group_info.group_id}")
|
||||
await self.heartflow_message_receiver.process_message(message)
|
||||
if ENABLE_S4U_CHAT:
|
||||
logger.info("进入S4U流程")
|
||||
await self.s4u_message_processor.process_message(message)
|
||||
return
|
||||
|
||||
await self.heartflow_message_receiver.process_message(message)
|
||||
|
||||
if template_group_name:
|
||||
async with global_prompt_manager.async_message_scope(template_group_name):
|
||||
|
||||
@@ -336,6 +336,9 @@ class DefaultReplyer:
|
||||
return False, None
|
||||
|
||||
async def build_relation_info(self, reply_data=None, chat_history=None):
|
||||
if not global_config.relationship.enable_relationship:
|
||||
return ""
|
||||
|
||||
relationship_fetcher = relationship_fetcher_manager.get_fetcher(self.chat_stream.stream_id)
|
||||
if not reply_data:
|
||||
return ""
|
||||
@@ -355,6 +358,9 @@ class DefaultReplyer:
|
||||
return relation_info
|
||||
|
||||
async def build_expression_habits(self, chat_history, target):
|
||||
if not global_config.expression.enable_expression:
|
||||
return ""
|
||||
|
||||
style_habbits = []
|
||||
grammar_habbits = []
|
||||
|
||||
@@ -390,6 +396,9 @@ class DefaultReplyer:
|
||||
return expression_habits_block
|
||||
|
||||
async def build_memory_block(self, chat_history, target):
|
||||
if not global_config.memory.enable_memory:
|
||||
return ""
|
||||
|
||||
running_memorys = await self.memory_activator.activate_memory_with_chat_history(
|
||||
target_message=target, chat_history_prompt=chat_history
|
||||
)
|
||||
@@ -415,6 +424,7 @@ class DefaultReplyer:
|
||||
Returns:
|
||||
str: 工具信息字符串
|
||||
"""
|
||||
|
||||
if not reply_data:
|
||||
return ""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user