v0.2修改了一些东西
使概率配置生效 将一些模块解耦合 将组信息管理器合并到关系管理器,添加了可以全局调用的接口 精简了llm生成器的代码 精简了message代码 重写了回复后处理
This commit is contained in:
13
README.md
13
README.md
@@ -4,7 +4,7 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||

|

|
||||||

|
<!--  -->
|
||||||

|

|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -15,7 +15,8 @@
|
|||||||
|
|
||||||
基于napcat、nonebot和mongodb的专注于群聊天的qqbot
|
基于napcat、nonebot和mongodb的专注于群聊天的qqbot
|
||||||
|
|
||||||
> ⚠️ **警告**:代码可能随时更改,目前版本不一定是稳定版本,请自行了解qqbot的风险
|
> ⚠️ **警告**:代码可能随时更改,目前版本不一定是稳定版本,并请自行了解qqbot的风险
|
||||||
|
> ⚠️ **警告**:由于麦麦一直在迭代,所以可能存在一些bug,请自行测试,包括胡言乱语(
|
||||||
|
|
||||||
## 🚀 快速开始
|
## 🚀 快速开始
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@
|
|||||||
## 🎯 功能介绍
|
## 🎯 功能介绍
|
||||||
|
|
||||||
### 💬 聊天功能
|
### 💬 聊天功能
|
||||||
- 支持关键词检索主动发言:对消息的话题topic进行识别,如果检测到麦麦存储过的话题就会主动进行发言,没写完
|
- 支持关键词检索主动发言:对消息的话题topic进行识别,如果检测到麦麦存储过的话题就会主动进行发言,目前有bug
|
||||||
- 支持bot名字呼唤发言:检测到"麦麦"会主动发言,可配置
|
- 支持bot名字呼唤发言:检测到"麦麦"会主动发言,可配置
|
||||||
- 使用硅基流动的api进行回复生成,可随机使用R1,V3,R1-distill等模型,未来将加入官网api支持
|
- 使用硅基流动的api进行回复生成,可随机使用R1,V3,R1-distill等模型,未来将加入官网api支持
|
||||||
- 动态的prompt构建器,更拟人
|
- 动态的prompt构建器,更拟人
|
||||||
@@ -53,7 +54,7 @@
|
|||||||
|
|
||||||
### 😊 表情包功能
|
### 😊 表情包功能
|
||||||
- 支持根据发言内容发送对应情绪的表情包:未完善,可以用
|
- 支持根据发言内容发送对应情绪的表情包:未完善,可以用
|
||||||
- 会自动偷群友的表情包(未完善,暂时禁用)
|
- 会自动偷群友的表情包(未完善,暂时禁用)目前有bug
|
||||||
|
|
||||||
### 📅 日程功能
|
### 📅 日程功能
|
||||||
- 麦麦会自动生成一天的日程,实现更拟人的回复
|
- 麦麦会自动生成一天的日程,实现更拟人的回复
|
||||||
@@ -64,11 +65,9 @@
|
|||||||
### 📚 知识库功能
|
### 📚 知识库功能
|
||||||
- 基于embedding模型的知识库,手动放入txt会自动识别,写完了,暂时禁用
|
- 基于embedding模型的知识库,手动放入txt会自动识别,写完了,暂时禁用
|
||||||
|
|
||||||
### 📊 可视化的界面
|
|
||||||
- 基于gradio的后台界面,可以显示实时消息,思考过程和消息发送流(WIP)
|
|
||||||
|
|
||||||
### 👥 关系功能
|
### 👥 关系功能
|
||||||
- 针对每个用户创建"关系",可以对不同用户进行个性化回复,目前只有极其简单的好感度(WIP)
|
- 针对每个用户创建"关系",可以对不同用户进行个性化回复,目前只有极其简单的好感度(WIP)
|
||||||
|
- 针对每个群创建"群印象",可以对不同群进行个性化回复(WIP)
|
||||||
|
|
||||||
## 🚧 开发中功能
|
## 🚧 开发中功能
|
||||||
- 人格功能:WIP
|
- 人格功能:WIP
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from .llm_generator import LLMResponseGenerator
|
|||||||
from .message_stream import MessageStream, MessageStreamContainer
|
from .message_stream import MessageStream, MessageStreamContainer
|
||||||
from .topic_identifier import topic_identifier
|
from .topic_identifier import topic_identifier
|
||||||
from random import random
|
from random import random
|
||||||
from .group_info_manager import GroupInfoManager # 导入群信息管理器
|
|
||||||
from .emoji_manager import emoji_manager # 导入表情包管理器
|
from .emoji_manager import emoji_manager # 导入表情包管理器
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
@@ -15,14 +14,13 @@ from .message_send_control import message_sender # 导入消息发送控制器
|
|||||||
from .message import Message_Thinking # 导入 Message_Thinking 类
|
from .message import Message_Thinking # 导入 Message_Thinking 类
|
||||||
from .relationship_manager import relationship_manager
|
from .relationship_manager import relationship_manager
|
||||||
from .willing_manager import willing_manager # 导入意愿管理器
|
from .willing_manager import willing_manager # 导入意愿管理器
|
||||||
|
from .utils import is_mentioned_bot_in_txt, calculate_typing_time
|
||||||
|
|
||||||
class ChatBot:
|
class ChatBot:
|
||||||
def __init__(self, config: BotConfig):
|
def __init__(self, config: BotConfig):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.storage = MessageStorage()
|
self.storage = MessageStorage()
|
||||||
self.gpt = LLMResponseGenerator(config)
|
self.gpt = LLMResponseGenerator(config)
|
||||||
self.group_info_manager = GroupInfoManager() # 初始化群信息管理器
|
|
||||||
self.bot = None # bot 实例引用
|
self.bot = None # bot 实例引用
|
||||||
self._started = False
|
self._started = False
|
||||||
|
|
||||||
@@ -79,26 +77,19 @@ class ChatBot:
|
|||||||
# print(f"- original_message: {event.reply.original_message}")
|
# print(f"- original_message: {event.reply.original_message}")
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# 获取群组信息,发送消息的用户信息,并对数据库内容做一次更新
|
|
||||||
|
|
||||||
group_info = await bot.get_group_info(group_id=event.group_id)
|
group_info = await bot.get_group_info(group_id=event.group_id)
|
||||||
await self.group_info_manager.update_group_info(
|
|
||||||
group_id=event.group_id,
|
|
||||||
group_name=group_info['group_name'],
|
|
||||||
member_count=group_info['member_count']
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
sender_info = await bot.get_group_member_info(group_id=event.group_id, user_id=event.user_id, no_cache=True)
|
sender_info = await bot.get_group_member_info(group_id=event.group_id, user_id=event.user_id, no_cache=True)
|
||||||
|
|
||||||
# print(f"\033[1;32m[关系管理]\033[0m 更新关系: {sender_info}")
|
|
||||||
|
|
||||||
await relationship_manager.update_relationship(user_id = event.user_id, data = sender_info)
|
await relationship_manager.update_relationship(user_id = event.user_id, data = sender_info)
|
||||||
await relationship_manager.update_relationship_value(user_id = event.user_id, relationship_value = 0.5)
|
await relationship_manager.update_relationship_value(user_id = event.user_id, relationship_value = 0.5)
|
||||||
print(f"\033[1;32m[关系管理]\033[0m 更新关系值: {relationship_manager.get_relationship(event.user_id).relationship_value}")
|
print(f"\033[1;32m[关系管理]\033[0m 更新关系值: {relationship_manager.get_relationship(event.user_id).relationship_value}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
message = Message(
|
message = Message(
|
||||||
group_id=event.group_id,
|
group_id=event.group_id,
|
||||||
user_id=event.user_id,
|
user_id=event.user_id,
|
||||||
@@ -113,13 +104,12 @@ class ChatBot:
|
|||||||
topic = topic_identifier.identify_topic_jieba(message.processed_plain_text)
|
topic = topic_identifier.identify_topic_jieba(message.processed_plain_text)
|
||||||
print(f"\033[1;32m[主题识别]\033[0m 主题: {topic}")
|
print(f"\033[1;32m[主题识别]\033[0m 主题: {topic}")
|
||||||
|
|
||||||
|
|
||||||
await self.storage.store_message(message, topic[0] if topic else None)
|
await self.storage.store_message(message, topic[0] if topic else None)
|
||||||
|
|
||||||
current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(message.time))
|
|
||||||
|
|
||||||
print(f"\033[1;34m[调试]\033[0m 当前消息是否是表情包: {message.is_emoji}")
|
|
||||||
|
|
||||||
is_mentioned = self.is_mentioned_bot(message)
|
is_mentioned = is_mentioned_bot_in_txt(message.processed_plain_text)
|
||||||
reply_probability = willing_manager.change_reply_willing_received(
|
reply_probability = willing_manager.change_reply_willing_received(
|
||||||
event.group_id,
|
event.group_id,
|
||||||
topic[0] if topic else None,
|
topic[0] if topic else None,
|
||||||
@@ -133,28 +123,31 @@ class ChatBot:
|
|||||||
|
|
||||||
print(f"\033[1;32m[{current_time}][{message.group_name}]{message.user_nickname}:\033[0m {message.processed_plain_text}\033[1;36m[回复意愿:{current_willing:.2f}][概率:{reply_probability:.1f}]\033[0m")
|
print(f"\033[1;32m[{current_time}][{message.group_name}]{message.user_nickname}:\033[0m {message.processed_plain_text}\033[1;36m[回复意愿:{current_willing:.2f}][概率:{reply_probability:.1f}]\033[0m")
|
||||||
response = ""
|
response = ""
|
||||||
|
# 创建思考消息
|
||||||
if random() < reply_probability:
|
if random() < reply_probability:
|
||||||
|
|
||||||
tinking_time_point = round(time.time(), 2)
|
tinking_time_point = round(time.time(), 2)
|
||||||
think_id = 'mt' + str(tinking_time_point)
|
think_id = 'mt' + str(tinking_time_point)
|
||||||
|
|
||||||
thinking_message = Message_Thinking(message=message,message_id=think_id)
|
thinking_message = Message_Thinking(message=message,message_id=think_id)
|
||||||
|
|
||||||
message_sender.send_temp_container.add_message(thinking_message)
|
message_sender.send_temp_container.add_message(thinking_message)
|
||||||
|
|
||||||
willing_manager.change_reply_willing_sent(thinking_message.group_id)
|
willing_manager.change_reply_willing_sent(thinking_message.group_id)
|
||||||
# 生成回复
|
|
||||||
response, emotion = await self.gpt.generate_response(message)
|
response, emotion = await self.gpt.generate_response(message)
|
||||||
|
|
||||||
# 如果生成了回复,发送并记录
|
# 如果生成了回复,发送并记录
|
||||||
|
|
||||||
|
|
||||||
if response:
|
if response:
|
||||||
message_set = MessageSet(event.group_id, self.config.BOT_QQ, think_id)
|
message_set = MessageSet(event.group_id, self.config.BOT_QQ, think_id)
|
||||||
if isinstance(response, list):
|
accu_typing_time = 0
|
||||||
# 将多条消息合并成一条
|
|
||||||
for msg in response:
|
for msg in response:
|
||||||
# print(f"\033[1;34m[调试]\033[0m 载入消息消息: {msg}")
|
print(f"当前消息: {msg}")
|
||||||
# bot_response_time = round(time.time(), 2)
|
typing_time = calculate_typing_time(msg)
|
||||||
timepoint = tinking_time_point-0.3
|
accu_typing_time += typing_time
|
||||||
|
timepoint = tinking_time_point+accu_typing_time
|
||||||
|
# print(f"\033[1;32m[调试]\033[0m 消息: {msg},添加!, 累计打字时间: {accu_typing_time:.2f}秒")
|
||||||
|
|
||||||
bot_message = Message(
|
bot_message = Message(
|
||||||
group_id=event.group_id,
|
group_id=event.group_id,
|
||||||
user_id=self.config.BOT_QQ,
|
user_id=self.config.BOT_QQ,
|
||||||
@@ -167,26 +160,10 @@ class ChatBot:
|
|||||||
group_name=message.group_name,
|
group_name=message.group_name,
|
||||||
time=timepoint
|
time=timepoint
|
||||||
)
|
)
|
||||||
# print(f"\033[1;34m[调试]\033[0m 添加消息到消息组: {bot_message}")
|
|
||||||
message_set.add_message(bot_message)
|
message_set.add_message(bot_message)
|
||||||
# print(f"\033[1;34m[调试]\033[0m 输入消息组: {message_set}")
|
|
||||||
message_sender.send_temp_container.update_thinking_message(message_set)
|
message_sender.send_temp_container.update_thinking_message(message_set)
|
||||||
else:
|
|
||||||
# bot_response_time = round(time.time(), 2)
|
|
||||||
bot_message = Message(
|
|
||||||
group_id=event.group_id,
|
|
||||||
user_id=self.config.BOT_QQ,
|
|
||||||
message_id=think_id,
|
|
||||||
message_based_id=event.message_id,
|
|
||||||
raw_message=response,
|
|
||||||
plain_text=response,
|
|
||||||
processed_plain_text=response,
|
|
||||||
user_nickname="麦麦",
|
|
||||||
group_name=message.group_name,
|
|
||||||
time=tinking_time_point
|
|
||||||
)
|
|
||||||
# print(f"\033[1;34m[调试]\033[0m 更新单条消息: {bot_message}")
|
|
||||||
message_sender.send_temp_container.update_thinking_message(bot_message)
|
|
||||||
|
|
||||||
|
|
||||||
bot_response_time = tinking_time_point
|
bot_response_time = tinking_time_point
|
||||||
@@ -197,8 +174,8 @@ class ChatBot:
|
|||||||
|
|
||||||
if random() < 0.5:
|
if random() < 0.5:
|
||||||
bot_response_time = tinking_time_point - 1
|
bot_response_time = tinking_time_point - 1
|
||||||
# else:
|
else:
|
||||||
# bot_response_time = bot_response_time + 1
|
bot_response_time = bot_response_time + 1
|
||||||
|
|
||||||
bot_message = Message(
|
bot_message = Message(
|
||||||
group_id=event.group_id,
|
group_id=event.group_id,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ name = "MegBot"
|
|||||||
|
|
||||||
[bot]
|
[bot]
|
||||||
qq = #填入你的机器人QQ
|
qq = #填入你的机器人QQ
|
||||||
|
nickname = "麦麦"
|
||||||
|
|
||||||
[message]
|
[message]
|
||||||
min_text_length = 2
|
min_text_length = 2
|
||||||
@@ -16,7 +17,9 @@ check_interval = 120
|
|||||||
register_interval = 10
|
register_interval = 10
|
||||||
|
|
||||||
[response]
|
[response]
|
||||||
model_r1_probability = 0.2 #使用R1回复的概率(没启用)
|
model_r1_probability = 0.8
|
||||||
|
model_v3_probability = 0.1
|
||||||
|
model_r1_distill_probability = 0.1
|
||||||
|
|
||||||
|
|
||||||
[groups]
|
[groups]
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class BotConfig:
|
|||||||
DATABASE_NAME: str = "MegBot"
|
DATABASE_NAME: str = "MegBot"
|
||||||
|
|
||||||
BOT_QQ: Optional[int] = None
|
BOT_QQ: Optional[int] = None
|
||||||
|
BOT_NICKNAME: Optional[str] = None
|
||||||
|
|
||||||
# 消息处理相关配置
|
# 消息处理相关配置
|
||||||
MIN_TEXT_LENGTH: int = 2 # 最小处理文本长度
|
MIN_TEXT_LENGTH: int = 2 # 最小处理文本长度
|
||||||
@@ -39,7 +40,9 @@ class BotConfig:
|
|||||||
EMOJI_CHECK_INTERVAL: int = 120 # 表情包检查间隔(分钟)
|
EMOJI_CHECK_INTERVAL: int = 120 # 表情包检查间隔(分钟)
|
||||||
EMOJI_REGISTER_INTERVAL: int = 10 # 表情包注册间隔(分钟)
|
EMOJI_REGISTER_INTERVAL: int = 10 # 表情包注册间隔(分钟)
|
||||||
|
|
||||||
MODEL_R1_PROBABILITY: float = 0.3 # R1模型概率
|
MODEL_R1_PROBABILITY: float = 0.8 # R1模型概率
|
||||||
|
MODEL_V3_PROBABILITY: float = 0.1 # V3模型概率
|
||||||
|
MODEL_R1_DISTILL_PROBABILITY: float = 0.1 # R1蒸馏模型概率
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_config(cls, config_path: str = "bot_config.toml") -> "BotConfig":
|
def load_config(cls, config_path: str = "bot_config.toml") -> "BotConfig":
|
||||||
@@ -66,11 +69,13 @@ class BotConfig:
|
|||||||
bot_config = toml_dict["bot"]
|
bot_config = toml_dict["bot"]
|
||||||
bot_qq = bot_config.get("qq")
|
bot_qq = bot_config.get("qq")
|
||||||
config.BOT_QQ = int(bot_qq)
|
config.BOT_QQ = int(bot_qq)
|
||||||
|
config.BOT_NICKNAME = bot_config.get("nickname", config.BOT_NICKNAME)
|
||||||
|
|
||||||
if "response" in toml_dict:
|
if "response" in toml_dict:
|
||||||
response_config = toml_dict["response"]
|
response_config = toml_dict["response"]
|
||||||
config.MODEL_R1_PROBABILITY = response_config.get("model_r1_probability", config.MODEL_R1_PROBABILITY)
|
config.MODEL_R1_PROBABILITY = response_config.get("model_r1_probability", config.MODEL_R1_PROBABILITY)
|
||||||
|
config.MODEL_V3_PROBABILITY = response_config.get("model_v3_probability", config.MODEL_V3_PROBABILITY)
|
||||||
|
config.MODEL_R1_DISTILL_PROBABILITY = response_config.get("model_r1_distill_probability", config.MODEL_R1_DISTILL_PROBABILITY)
|
||||||
|
|
||||||
# 消息配置
|
# 消息配置
|
||||||
if "message" in toml_dict:
|
if "message" in toml_dict:
|
||||||
|
|||||||
@@ -1,107 +0,0 @@
|
|||||||
from typing import Dict, Optional
|
|
||||||
from ...common.database import Database
|
|
||||||
import time
|
|
||||||
|
|
||||||
class GroupInfoManager:
|
|
||||||
def __init__(self):
|
|
||||||
self.db = Database.get_instance()
|
|
||||||
# 确保必要的集合存在
|
|
||||||
self._ensure_collections()
|
|
||||||
|
|
||||||
def _ensure_collections(self):
|
|
||||||
"""确保数据库中有必要的集合"""
|
|
||||||
collections = self.db.db.list_collection_names()
|
|
||||||
if 'group_info' not in collections:
|
|
||||||
self.db.db.create_collection('group_info')
|
|
||||||
if 'user_info' not in collections:
|
|
||||||
self.db.db.create_collection('user_info')
|
|
||||||
|
|
||||||
async def update_group_info(self, group_id: int, group_name: str, group_notice: str = "",
|
|
||||||
member_count: int = 0, admins: list = None):
|
|
||||||
"""更新群组信息"""
|
|
||||||
try:
|
|
||||||
group_data = {
|
|
||||||
"group_id": group_id,
|
|
||||||
"group_name": group_name,
|
|
||||||
"group_notice": group_notice,
|
|
||||||
"member_count": member_count,
|
|
||||||
"admins": admins or [],
|
|
||||||
"last_updated": time.time()
|
|
||||||
}
|
|
||||||
|
|
||||||
# 使用 upsert 来更新或插入数据
|
|
||||||
self.db.db.group_info.update_one(
|
|
||||||
{"group_id": group_id},
|
|
||||||
{"$set": group_data},
|
|
||||||
upsert=True
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"\033[1;31m[错误]\033[0m 更新群信息失败: {str(e)}")
|
|
||||||
|
|
||||||
async def update_user_info(self, user_id: int, nickname: str, group_id: int = None,
|
|
||||||
group_card: str = None, age: int = None, gender: str = None,
|
|
||||||
location: str = None):
|
|
||||||
"""更新用户信息"""
|
|
||||||
try:
|
|
||||||
# 基础用户数据
|
|
||||||
user_data = {
|
|
||||||
"user_id": user_id,
|
|
||||||
"nickname": nickname,
|
|
||||||
"last_updated": time.time()
|
|
||||||
}
|
|
||||||
|
|
||||||
# 添加可选字段
|
|
||||||
if age is not None:
|
|
||||||
user_data["age"] = age
|
|
||||||
if gender is not None:
|
|
||||||
user_data["gender"] = gender
|
|
||||||
if location is not None:
|
|
||||||
user_data["location"] = location
|
|
||||||
|
|
||||||
# 如果提供了群相关信息,更新用户在该群的信息
|
|
||||||
if group_id is not None:
|
|
||||||
group_info_key = f"group_info.{group_id}"
|
|
||||||
group_data = {
|
|
||||||
group_info_key: {
|
|
||||||
"group_card": group_card,
|
|
||||||
"last_active": time.time()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
user_data.update(group_data)
|
|
||||||
|
|
||||||
# 使用 upsert 来更新或插入数据
|
|
||||||
result = self.db.db.user_info.update_one(
|
|
||||||
{"user_id": user_id},
|
|
||||||
{
|
|
||||||
"$set": user_data,
|
|
||||||
"$addToSet": {"groups": group_id} if group_id else {}
|
|
||||||
},
|
|
||||||
upsert=True
|
|
||||||
)
|
|
||||||
|
|
||||||
# print(f"\033[1;32m[用户信息]\033[0m 更新用户 {nickname}({user_id}) 的信息 {'成功' if result.modified_count > 0 or result.upserted_id else '未变化'}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"\033[1;31m[错误]\033[0m 更新用户信息失败: {str(e)}")
|
|
||||||
print(f"用户ID: {user_id}, 昵称: {nickname}, 群ID: {group_id}, 群名片: {group_card}")
|
|
||||||
|
|
||||||
async def get_group_info(self, group_id: int) -> Optional[Dict]:
|
|
||||||
"""获取群组信息"""
|
|
||||||
try:
|
|
||||||
return self.db.db.group_info.find_one({"group_id": group_id})
|
|
||||||
except Exception as e:
|
|
||||||
print(f"\033[1;31m[错误]\033[0m 获取群信息失败: {str(e)}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
async def get_user_info(self, user_id: int, group_id: int = None) -> Optional[Dict]:
|
|
||||||
"""获取用户信息"""
|
|
||||||
try:
|
|
||||||
user_info = self.db.db.user_info.find_one({"user_id": user_id})
|
|
||||||
if user_info and group_id:
|
|
||||||
# 添加该用户在特定群的信息
|
|
||||||
group_info_key = f"group_info.{group_id}"
|
|
||||||
user_info["current_group_info"] = user_info.get(group_info_key, {})
|
|
||||||
return user_info
|
|
||||||
except Exception as e:
|
|
||||||
print(f"\033[1;31m[错误]\033[0m 获取用户信息失败: {str(e)}")
|
|
||||||
return None
|
|
||||||
@@ -14,8 +14,8 @@ from dotenv import load_dotenv
|
|||||||
from .relationship_manager import relationship_manager
|
from .relationship_manager import relationship_manager
|
||||||
from ..schedule.schedule_generator import bot_schedule
|
from ..schedule.schedule_generator import bot_schedule
|
||||||
from .prompt_builder import prompt_builder
|
from .prompt_builder import prompt_builder
|
||||||
from .config import llm_config
|
from .config import llm_config, global_config
|
||||||
from .utils import get_embedding, split_into_sentences, process_text_with_typos
|
from .utils import process_llm_response
|
||||||
|
|
||||||
|
|
||||||
# 获取当前文件的绝对路径
|
# 获取当前文件的绝对路径
|
||||||
@@ -38,14 +38,19 @@ class LLMResponseGenerator:
|
|||||||
|
|
||||||
async def generate_response(self, message: Message) -> Optional[Union[str, List[str]]]:
|
async def generate_response(self, message: Message) -> Optional[Union[str, List[str]]]:
|
||||||
"""根据当前模型类型选择对应的生成函数"""
|
"""根据当前模型类型选择对应的生成函数"""
|
||||||
# 使用随机数选择模型
|
# 从global_config中获取模型概率值
|
||||||
|
model_r1_probability = global_config.MODEL_R1_PROBABILITY
|
||||||
|
model_v3_probability = global_config.MODEL_V3_PROBABILITY
|
||||||
|
model_r1_distill_probability = global_config.MODEL_R1_DISTILL_PROBABILITY
|
||||||
|
|
||||||
|
# 生成随机数并根据概率选择模型
|
||||||
rand = random.random()
|
rand = random.random()
|
||||||
if rand < 0.8: # 60%概率使用 R1
|
if rand < model_r1_probability:
|
||||||
self.current_model_type = "r1"
|
self.current_model_type = 'r1'
|
||||||
elif rand < 0.5: # 20%概率使用 V3
|
elif rand < model_r1_probability + model_v3_probability:
|
||||||
self.current_model_type = "v3"
|
self.current_model_type = 'v3'
|
||||||
else: # 20%概率使用 R1-Distill
|
else:
|
||||||
self.current_model_type = "r1_distill"
|
self.current_model_type = 'r1_distill' # 默认使用 R1-Distill
|
||||||
|
|
||||||
print(f"+++++++++++++++++麦麦{self.current_model_type}思考中+++++++++++++++++")
|
print(f"+++++++++++++++++麦麦{self.current_model_type}思考中+++++++++++++++++")
|
||||||
if self.current_model_type == 'r1':
|
if self.current_model_type == 'r1':
|
||||||
@@ -64,11 +69,15 @@ class LLMResponseGenerator:
|
|||||||
|
|
||||||
return model_response, emotion
|
return model_response, emotion
|
||||||
|
|
||||||
async def _generate_r1_response(self, message: Message) -> Optional[str]:
|
async def _generate_base_response(
|
||||||
"""使用 DeepSeek-R1 模型生成回复"""
|
self,
|
||||||
# 获取群聊上下文
|
message: Message,
|
||||||
group_chat = await self._get_group_chat_context(message)
|
model_name: str,
|
||||||
|
model_params: Optional[Dict[str, Any]] = None
|
||||||
|
) -> Optional[str]:
|
||||||
sender_name = message.user_nickname or f"用户{message.user_id}"
|
sender_name = message.user_nickname or f"用户{message.user_id}"
|
||||||
|
|
||||||
|
# 获取关系值
|
||||||
if relationship_manager.get_relationship(message.user_id):
|
if relationship_manager.get_relationship(message.user_id):
|
||||||
relationship_value = relationship_manager.get_relationship(message.user_id).relationship_value
|
relationship_value = relationship_manager.get_relationship(message.user_id).relationship_value
|
||||||
print(f"\033[1;32m[关系管理]\033[0m 回复中_当前关系值: {relationship_value}")
|
print(f"\033[1;32m[关系管理]\033[0m 回复中_当前关系值: {relationship_value}")
|
||||||
@@ -83,18 +92,30 @@ class LLMResponseGenerator:
|
|||||||
group_id=message.group_id
|
group_id=message.group_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 设置默认参数
|
||||||
|
default_params = {
|
||||||
|
"model": model_name,
|
||||||
|
"messages": [{"role": "user", "content": prompt}],
|
||||||
|
"stream": False,
|
||||||
|
"max_tokens": 1024,
|
||||||
|
"temperature": 0.7
|
||||||
|
}
|
||||||
|
|
||||||
|
# 更新参数
|
||||||
|
if model_params:
|
||||||
|
default_params.update(model_params)
|
||||||
|
|
||||||
def create_completion():
|
def create_completion():
|
||||||
return self.client.chat.completions.create(
|
return self.client.chat.completions.create(**default_params)
|
||||||
model="Pro/deepseek-ai/DeepSeek-R1",
|
|
||||||
messages=[{"role": "user", "content": prompt}],
|
|
||||||
stream=False,
|
|
||||||
max_tokens=1024
|
|
||||||
)
|
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
response = await loop.run_in_executor(None, create_completion)
|
response = await loop.run_in_executor(None, create_completion)
|
||||||
if response.choices[0].message.content:
|
|
||||||
|
if not response.choices[0].message.content:
|
||||||
|
return None
|
||||||
|
|
||||||
content = response.choices[0].message.content
|
content = response.choices[0].message.content
|
||||||
|
|
||||||
# 获取推理内容
|
# 获取推理内容
|
||||||
reasoning_content = "模型思考过程:\n" + prompt
|
reasoning_content = "模型思考过程:\n" + prompt
|
||||||
if hasattr(response.choices[0].message, "reasoning"):
|
if hasattr(response.choices[0].message, "reasoning"):
|
||||||
@@ -102,124 +123,45 @@ class LLMResponseGenerator:
|
|||||||
elif hasattr(response.choices[0].message, "reasoning_content"):
|
elif hasattr(response.choices[0].message, "reasoning_content"):
|
||||||
reasoning_content = response.choices[0].message.reasoning_content or reasoning_content
|
reasoning_content = response.choices[0].message.reasoning_content or reasoning_content
|
||||||
|
|
||||||
# 保存推理结果到数据库
|
# 保存到数据库
|
||||||
self.db.db.reasoning_logs.insert_one({
|
self.db.db.reasoning_logs.insert_one({
|
||||||
'time': time.time(),
|
'time': time.time(),
|
||||||
'group_id': message.group_id,
|
'group_id': message.group_id,
|
||||||
'user': sender_name,
|
'user': sender_name,
|
||||||
'message': message.processed_plain_text,
|
'message': message.processed_plain_text,
|
||||||
'model': "DeepSeek-R1",
|
'model': model_name,
|
||||||
'reasoning': reasoning_content,
|
'reasoning': reasoning_content,
|
||||||
'response': content,
|
'response': content,
|
||||||
'prompt': prompt
|
'prompt': prompt,
|
||||||
|
'model_params': default_params
|
||||||
})
|
})
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
async def _generate_r1_response(self, message: Message) -> Optional[str]:
|
||||||
|
"""使用 DeepSeek-R1 模型生成回复"""
|
||||||
|
return await self._generate_base_response(
|
||||||
|
message,
|
||||||
|
"Pro/deepseek-ai/DeepSeek-R1",
|
||||||
|
{"temperature": 0.7, "max_tokens": 1024}
|
||||||
|
)
|
||||||
|
|
||||||
async def _generate_v3_response(self, message: Message) -> Optional[str]:
|
async def _generate_v3_response(self, message: Message) -> Optional[str]:
|
||||||
"""使用 DeepSeek-V3 模型生成回复"""
|
"""使用 DeepSeek-V3 模型生成回复"""
|
||||||
# 获取群聊上下文
|
return await self._generate_base_response(
|
||||||
group_chat = await self._get_group_chat_context(message)
|
message,
|
||||||
sender_name = message.user_nickname or f"用户{message.user_id}"
|
"Pro/deepseek-ai/DeepSeek-V3",
|
||||||
|
{"temperature": 0.8, "max_tokens": 1024}
|
||||||
if relationship_manager.get_relationship(message.user_id):
|
|
||||||
relationship_value = relationship_manager.get_relationship(message.user_id).relationship_value
|
|
||||||
print(f"\033[1;32m[关系管理]\033[0m 回复中_当前关系值: {relationship_value}")
|
|
||||||
else:
|
|
||||||
relationship_value = 0.0
|
|
||||||
|
|
||||||
prompt = prompt_builder._build_prompt(message.processed_plain_text, sender_name, relationship_value, group_id=message.group_id)
|
|
||||||
|
|
||||||
messages = [{"role": "user", "content": prompt}]
|
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
create_completion = partial(
|
|
||||||
self.client.chat.completions.create,
|
|
||||||
model="Pro/deepseek-ai/DeepSeek-V3",
|
|
||||||
messages=messages,
|
|
||||||
stream=False,
|
|
||||||
max_tokens=1024,
|
|
||||||
temperature=0.8
|
|
||||||
)
|
)
|
||||||
response = await loop.run_in_executor(None, create_completion)
|
|
||||||
|
|
||||||
if response.choices[0].message.content:
|
|
||||||
content = response.choices[0].message.content
|
|
||||||
# 保存推理结果到数据库
|
|
||||||
self.db.db.reasoning_logs.insert_one({
|
|
||||||
'time': time.time(),
|
|
||||||
'group_id': message.group_id,
|
|
||||||
'user': sender_name,
|
|
||||||
'message': message.processed_plain_text,
|
|
||||||
'model': "DeepSeek-V3",
|
|
||||||
'reasoning': "V3模型无推理过程",
|
|
||||||
'response': content,
|
|
||||||
'prompt': prompt
|
|
||||||
})
|
|
||||||
|
|
||||||
return content
|
|
||||||
else:
|
|
||||||
print(f"[ERROR] V3 回复发送生成失败: {response}")
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
async def _generate_r1_distill_response(self, message: Message) -> Optional[str]:
|
async def _generate_r1_distill_response(self, message: Message) -> Optional[str]:
|
||||||
"""使用 DeepSeek-R1-Distill-Qwen-32B 模型生成回复"""
|
"""使用 DeepSeek-R1-Distill-Qwen-32B 模型生成回复"""
|
||||||
# 获取群聊上下文
|
return await self._generate_base_response(
|
||||||
group_chat = await self._get_group_chat_context(message)
|
message,
|
||||||
sender_name = message.user_nickname or f"用户{message.user_id}"
|
"deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
|
||||||
if relationship_manager.get_relationship(message.user_id):
|
{"temperature": 0.7, "max_tokens": 1024}
|
||||||
relationship_value = relationship_manager.get_relationship(message.user_id).relationship_value
|
|
||||||
print(f"\033[1;32m[关系管理]\033[0m 回复中_当前关系值: {relationship_value}")
|
|
||||||
else:
|
|
||||||
relationship_value = 0.0
|
|
||||||
|
|
||||||
# 构建 prompt
|
|
||||||
prompt = prompt_builder._build_prompt(
|
|
||||||
message_txt=message.processed_plain_text,
|
|
||||||
sender_name=sender_name,
|
|
||||||
relationship_value=relationship_value,
|
|
||||||
group_id=message.group_id
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_completion():
|
|
||||||
return self.client.chat.completions.create(
|
|
||||||
model="deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
|
|
||||||
messages=[{"role": "user", "content": prompt}],
|
|
||||||
stream=False,
|
|
||||||
max_tokens=1024
|
|
||||||
)
|
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
|
||||||
response = await loop.run_in_executor(None, create_completion)
|
|
||||||
if response.choices[0].message.content:
|
|
||||||
content = response.choices[0].message.content
|
|
||||||
# 获取推理内容
|
|
||||||
reasoning_content = "模型思考过程:\n" + prompt
|
|
||||||
if hasattr(response.choices[0].message, "reasoning"):
|
|
||||||
reasoning_content = response.choices[0].message.reasoning or reasoning_content
|
|
||||||
elif hasattr(response.choices[0].message, "reasoning_content"):
|
|
||||||
reasoning_content = response.choices[0].message.reasoning_content or reasoning_content
|
|
||||||
|
|
||||||
# 保存推理结果到数据库
|
|
||||||
self.db.db.reasoning_logs.insert_one({
|
|
||||||
'time': time.time(),
|
|
||||||
'group_id': message.group_id,
|
|
||||||
'user': sender_name,
|
|
||||||
'message': message.processed_plain_text,
|
|
||||||
'model': "DeepSeek-R1-Distill",
|
|
||||||
'reasoning': reasoning_content,
|
|
||||||
'response': content,
|
|
||||||
'prompt': prompt
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
return content
|
|
||||||
|
|
||||||
async def _get_group_chat_context(self, message: Message) -> str:
|
async def _get_group_chat_context(self, message: Message) -> str:
|
||||||
"""获取群聊上下文"""
|
"""获取群聊上下文"""
|
||||||
recent_messages = self.db.db.messages.find(
|
recent_messages = self.db.db.messages.find(
|
||||||
@@ -271,46 +213,14 @@ class LLMResponseGenerator:
|
|||||||
print(f"获取情感标签时出错: {e}")
|
print(f"获取情感标签时出错: {e}")
|
||||||
return ["neutral"] # 发生错误时返回默认值
|
return ["neutral"] # 发生错误时返回默认值
|
||||||
|
|
||||||
async def _process_response(self, content: str) -> Tuple[Union[str, List[str]], List[str]]:
|
async def _process_response(self, content: str) -> Tuple[List[str], List[str]]:
|
||||||
"""处理响应内容,返回处理后的内容和情感标签"""
|
"""处理响应内容,返回处理后的内容和情感标签"""
|
||||||
if not content:
|
if not content:
|
||||||
return None, []
|
return None, []
|
||||||
|
|
||||||
# 检查回复是否过长(超过200个字符)
|
|
||||||
if len(content) > 200:
|
|
||||||
print(f"回复过长 ({len(content)} 字符),返回默认回复")
|
|
||||||
return "麦麦不知道哦", ["angry"]
|
|
||||||
|
|
||||||
emotion_tags = await self._get_emotion_tags(content)
|
emotion_tags = await self._get_emotion_tags(content)
|
||||||
|
|
||||||
# 添加错别字和处理标点符号
|
processed_response = process_llm_response(content)
|
||||||
processed_response = process_text_with_typos(content)
|
|
||||||
|
|
||||||
# 处理长消息
|
|
||||||
if len(processed_response) > 5:
|
|
||||||
sentences = split_into_sentences(processed_response)
|
|
||||||
print(f"分割后的句子: {sentences}")
|
|
||||||
messages = []
|
|
||||||
current_message = ""
|
|
||||||
|
|
||||||
for sentence in sentences:
|
|
||||||
if len(current_message) + len(sentence) <= 5:
|
|
||||||
current_message += ' '
|
|
||||||
current_message += sentence
|
|
||||||
else:
|
|
||||||
if current_message:
|
|
||||||
messages.append(current_message.strip())
|
|
||||||
current_message = sentence
|
|
||||||
|
|
||||||
if current_message:
|
|
||||||
messages.append(current_message.strip())
|
|
||||||
|
|
||||||
# 检查分割后的消息数量是否过多(超过3条)
|
|
||||||
if len(messages) > 3:
|
|
||||||
print(f"分割后消息数量过多 ({len(messages)} 条),返回默认回复")
|
|
||||||
return "麦麦不知道哦", ["angry"]
|
|
||||||
|
|
||||||
return messages, emotion_tags
|
|
||||||
|
|
||||||
return processed_response, emotion_tags
|
return processed_response, emotion_tags
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from PIL import Image
|
|||||||
from .config import BotConfig, global_config
|
from .config import BotConfig, global_config
|
||||||
import urllib3
|
import urllib3
|
||||||
from .cq_code import CQCode
|
from .cq_code import CQCode
|
||||||
|
from .utils_user import get_user_nickname
|
||||||
|
|
||||||
Message = ForwardRef('Message') # 添加这行
|
Message = ForwardRef('Message') # 添加这行
|
||||||
|
|
||||||
@@ -44,32 +45,19 @@ class Message:
|
|||||||
time: float = None
|
time: float = None
|
||||||
|
|
||||||
is_emoji: bool = False # 是否是表情包
|
is_emoji: bool = False # 是否是表情包
|
||||||
|
has_emoji: bool = False # 是否包含表情包
|
||||||
|
|
||||||
|
|
||||||
reply_benefits: float = 0.0
|
reply_benefits: float = 0.0
|
||||||
|
|
||||||
type: str = 'received' # 消息类型,可以是received或者send
|
type: str = 'received' # 消息类型,可以是received或者send
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""消息数据类:思考消息"""
|
|
||||||
|
|
||||||
# 思考状态相关属性
|
|
||||||
is_thinking: bool = False
|
|
||||||
thinking_text: str = "正在思考..."
|
|
||||||
thingking_start_time: float = None
|
|
||||||
thinking_time: float = 0
|
|
||||||
|
|
||||||
received_message = ''
|
|
||||||
thinking_response = ''
|
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
if self.time is None:
|
if self.time is None:
|
||||||
self.time = int(time.time())
|
self.time = int(time.time())
|
||||||
|
|
||||||
if not self.user_nickname:
|
if not self.user_nickname:
|
||||||
self.user_nickname = self.get_user_nickname(self.user_id)
|
self.user_nickname = get_user_nickname(self.user_id)
|
||||||
|
|
||||||
if not self.group_name:
|
if not self.group_name:
|
||||||
self.group_name = self.get_groupname(self.group_id)
|
self.group_name = self.get_groupname(self.group_id)
|
||||||
@@ -84,28 +72,6 @@ class Message:
|
|||||||
for seg in self.message_segments
|
for seg in self.message_segments
|
||||||
)
|
)
|
||||||
|
|
||||||
# print(f"\033[1;34m[调试]\033[0m pppttt消息: {self.processed_plain_text}")
|
|
||||||
def get_user_nickname(self, user_id: int) -> str:
|
|
||||||
"""
|
|
||||||
根据user_id获取用户昵称
|
|
||||||
如果数据库中找不到,则返回默认昵称
|
|
||||||
"""
|
|
||||||
if not user_id:
|
|
||||||
return "未知用户"
|
|
||||||
|
|
||||||
user_id = int(user_id)
|
|
||||||
if user_id == int(global_config.BOT_QQ):
|
|
||||||
return "麦麦"
|
|
||||||
|
|
||||||
# 使用数据库单例
|
|
||||||
db = Database.get_instance()
|
|
||||||
# 查找用户,打印查询条件和结果
|
|
||||||
query = {'user_id': user_id}
|
|
||||||
user = db.db.user_info.find_one(query)
|
|
||||||
if user:
|
|
||||||
return user.get('nickname') or f"用户{user_id}"
|
|
||||||
else:
|
|
||||||
return f"用户{user_id}"
|
|
||||||
|
|
||||||
def get_groupname(self, group_id: int) -> str:
|
def get_groupname(self, group_id: int) -> str:
|
||||||
if not group_id:
|
if not group_id:
|
||||||
@@ -127,7 +93,7 @@ class Message:
|
|||||||
返回的列表中每个元素都是字典,包含:
|
返回的列表中每个元素都是字典,包含:
|
||||||
- type: 'text' 或 CQ码类型
|
- type: 'text' 或 CQ码类型
|
||||||
- data: 对于text类型是文本内容,对于CQ码是参数字典
|
- data: 对于text类型是文本内容,对于CQ码是参数字典
|
||||||
- translated_text: 经过处理(如AI翻译)后的文本
|
- translated_text: 经过处理后的文本
|
||||||
"""
|
"""
|
||||||
segments = []
|
segments = []
|
||||||
start = 0
|
start = 0
|
||||||
@@ -200,11 +166,15 @@ class Message:
|
|||||||
|
|
||||||
start = cq_end + 1
|
start = cq_end + 1
|
||||||
|
|
||||||
# 检查是否只包含一个表情包CQ码
|
|
||||||
if len(segments) == 1 and segments[0]['type'] == 'image':
|
if len(segments) == 1 and segments[0]['type'] == 'image':
|
||||||
# 检查图片的 subtype 是否为 0(表情包)
|
|
||||||
if segments[0]['data'].get('subtype') == '0':
|
|
||||||
self.is_emoji = True
|
self.is_emoji = True
|
||||||
|
self.has_emoji_emoji = True
|
||||||
|
else:
|
||||||
|
for segment in segments:
|
||||||
|
if segment['type'] == 'image' and segment['data'].get('sub_type') == '1':
|
||||||
|
self.has_emoji_emoji = True
|
||||||
|
break
|
||||||
|
|
||||||
return segments
|
return segments
|
||||||
|
|
||||||
@@ -224,11 +194,6 @@ class Message_Thinking:
|
|||||||
self.time = int(time.time())
|
self.time = int(time.time())
|
||||||
self.thinking_time = 0
|
self.thinking_time = 0
|
||||||
|
|
||||||
def update_to_message(self, done_message: Message) -> Message:
|
|
||||||
"""更新为完整消息"""
|
|
||||||
|
|
||||||
return done_message
|
|
||||||
|
|
||||||
def update_thinking_time(self):
|
def update_thinking_time(self):
|
||||||
self.thinking_time = round(time.time(), 2) - self.time
|
self.thinking_time = round(time.time(), 2) - self.time
|
||||||
|
|
||||||
@@ -278,21 +243,6 @@ class MessageSet:
|
|||||||
|
|
||||||
return self.messages[left]
|
return self.messages[left]
|
||||||
|
|
||||||
def get_latest_message(self) -> Optional[Message]:
|
|
||||||
"""获取最新的消息"""
|
|
||||||
return self.messages[-1] if self.messages else None
|
|
||||||
|
|
||||||
def get_earliest_message(self) -> Optional[Message]:
|
|
||||||
"""获取最早的消息"""
|
|
||||||
return self.messages[0] if self.messages else None
|
|
||||||
|
|
||||||
def get_all_messages(self) -> List[Message]:
|
|
||||||
"""获取所有消息"""
|
|
||||||
return self.messages.copy()
|
|
||||||
|
|
||||||
def get_message_count(self) -> int:
|
|
||||||
"""获取消息数量"""
|
|
||||||
return len(self.messages)
|
|
||||||
|
|
||||||
def clear_messages(self) -> None:
|
def clear_messages(self) -> None:
|
||||||
"""清空所有消息"""
|
"""清空所有消息"""
|
||||||
@@ -311,10 +261,7 @@ class MessageSet:
|
|||||||
def __len__(self) -> int:
|
def __len__(self) -> int:
|
||||||
return len(self.messages)
|
return len(self.messages)
|
||||||
|
|
||||||
@property
|
|
||||||
def processed_plain_text(self) -> str:
|
|
||||||
"""获取所有消息的文本内容"""
|
|
||||||
return "\n".join(msg.processed_plain_text for msg in self.messages if msg.processed_plain_text)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from .message import Message, Message_Thinking, MessageSet
|
|||||||
from .cq_code import CQCode
|
from .cq_code import CQCode
|
||||||
from collections import deque
|
from collections import deque
|
||||||
import time
|
import time
|
||||||
from .storage import MessageStorage # 添加这行导入
|
from .storage import MessageStorage
|
||||||
from .config import global_config
|
from .config import global_config
|
||||||
from .message_visualizer import message_visualizer
|
from .message_visualizer import message_visualizer
|
||||||
|
|
||||||
@@ -50,11 +50,6 @@ class SendTemp:
|
|||||||
def get_earliest_message(self) -> Optional[Message]:
|
def get_earliest_message(self) -> Optional[Message]:
|
||||||
"""获取时间最早的消息"""
|
"""获取时间最早的消息"""
|
||||||
message = self.messages.popleft() if self.messages else None
|
message = self.messages.popleft() if self.messages else None
|
||||||
# 如果是思考中的消息且思考时间不够,重新加入队列
|
|
||||||
# if (isinstance(message, Message_Thinking) and
|
|
||||||
# time.time() - message.start_time < 2): # 最少思考2秒
|
|
||||||
# self.messages.appendleft(message)
|
|
||||||
# return None
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
def clear(self) -> None:
|
def clear(self) -> None:
|
||||||
@@ -120,16 +115,7 @@ class SendTempContainer:
|
|||||||
return list(self.temp_queues.keys())
|
return list(self.temp_queues.keys())
|
||||||
|
|
||||||
def update_thinking_message(self, message_obj: Union[Message, MessageSet]) -> bool:
|
def update_thinking_message(self, message_obj: Union[Message, MessageSet]) -> bool:
|
||||||
"""更新思考中的消息
|
|
||||||
|
|
||||||
Args:
|
|
||||||
message_obj: 要更新的消息对象,可以是单条消息或消息组
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: 更新是否成功
|
|
||||||
"""
|
|
||||||
queue = self.get_queue(message_obj.group_id)
|
queue = self.get_queue(message_obj.group_id)
|
||||||
|
|
||||||
# 使用列表解析找到匹配的消息索引
|
# 使用列表解析找到匹配的消息索引
|
||||||
matching_indices = [
|
matching_indices = [
|
||||||
i for i, msg in enumerate(queue.messages)
|
i for i, msg in enumerate(queue.messages)
|
||||||
@@ -181,43 +167,29 @@ class MessageSendControl:
|
|||||||
"""设置当前bot实例"""
|
"""设置当前bot实例"""
|
||||||
self._current_bot = bot
|
self._current_bot = bot
|
||||||
|
|
||||||
async def start_processor(self, bot: Bot):
|
async def process_group_messages(self, group_id: int):
|
||||||
"""启动消息处理器"""
|
|
||||||
self._current_bot = bot
|
|
||||||
|
|
||||||
while self._running:
|
|
||||||
await asyncio.sleep(1.5)
|
|
||||||
# 处理所有群组的消息队列
|
|
||||||
for group_id in self.send_temp_container.get_all_groups():
|
|
||||||
queue = self.send_temp_container.get_queue(group_id)
|
queue = self.send_temp_container.get_queue(group_id)
|
||||||
if queue.has_messages():
|
if queue.has_messages():
|
||||||
message = queue.peek_next()
|
message = queue.peek_next()
|
||||||
# print(f"\033[1;34m[调试]\033[0m 查看最早的消息: {message}")
|
# 处理消息的逻辑
|
||||||
if message:
|
|
||||||
if isinstance(message, Message_Thinking):
|
if isinstance(message, Message_Thinking):
|
||||||
# 如果是思考中的消息,检查是否需要继续等待
|
|
||||||
message.update_thinking_time()
|
message.update_thinking_time()
|
||||||
thinking_time = message.thinking_time
|
thinking_time = message.thinking_time
|
||||||
if thinking_time < 60: # 最少思考2秒
|
if thinking_time < 60: # 最少思考2秒
|
||||||
if int(thinking_time) % 10 == 0:
|
if int(thinking_time) % 10 == 0:
|
||||||
print(f"\033[1;34m[调试]\033[0m 消息正在思考中,已思考{thinking_time:.1f}秒")
|
print(f"\033[1;34m[调试]\033[0m 消息正在思考中,已思考{thinking_time:.1f}秒")
|
||||||
continue
|
return
|
||||||
else:
|
else:
|
||||||
print(f"\033[1;34m[调试]\033[0m 思考消息超时,移除")
|
print(f"\033[1;34m[调试]\033[0m 思考消息超时,移除")
|
||||||
queue.get_earliest_message() # 移除超时的思考消息
|
queue.get_earliest_message() # 移除超时的思考消息
|
||||||
|
return
|
||||||
elif isinstance(message, Message):
|
elif isinstance(message, Message):
|
||||||
message = queue.get_earliest_message()
|
message = queue.get_earliest_message()
|
||||||
if message and message.processed_plain_text:
|
if message and message.processed_plain_text:
|
||||||
print(f"- 群组: {group_id} - 内容: {message.processed_plain_text}")
|
print(f"- 群组: {group_id} - 内容: {message.processed_plain_text}")
|
||||||
|
|
||||||
cost_time = round(time.time(), 2) - message.time
|
cost_time = round(time.time(), 2) - message.time
|
||||||
# print(f"\033[1;34m[调试]\033[0m 消息发送111111时间: {cost_time}秒")
|
|
||||||
if cost_time > 40:
|
if cost_time > 40:
|
||||||
message.processed_plain_text = CQCode.create_reply_cq(message.message_based_id) + message.processed_plain_text
|
message.processed_plain_text = CQCode.create_reply_cq(message.message_based_id) + message.processed_plain_text
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cur_time = time.time()
|
cur_time = time.time()
|
||||||
await self._current_bot.send_group_msg(
|
await self._current_bot.send_group_msg(
|
||||||
group_id=group_id,
|
group_id=group_id,
|
||||||
@@ -226,14 +198,10 @@ class MessageSendControl:
|
|||||||
)
|
)
|
||||||
cost_time = round(time.time(), 2) - cur_time
|
cost_time = round(time.time(), 2) - cur_time
|
||||||
print(f"\033[1;34m[调试]\033[0m 消息发送时间: {cost_time}秒")
|
print(f"\033[1;34m[调试]\033[0m 消息发送时间: {cost_time}秒")
|
||||||
|
|
||||||
|
|
||||||
current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(message.time))
|
current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(message.time))
|
||||||
print(f"\033[1;32m群 {group_id} 消息, 用户 麦麦, 时间: {current_time}:\033[0m {str(message.processed_plain_text)}")
|
print(f"\033[1;32m群 {group_id} 消息, 用户 麦麦, 时间: {current_time}:\033[0m {str(message.processed_plain_text)}")
|
||||||
await self.storage.store_message(message, None)
|
await self.storage.store_message(message, None)
|
||||||
|
|
||||||
queue.update_send_time()
|
queue.update_send_time()
|
||||||
|
|
||||||
if queue.has_messages():
|
if queue.has_messages():
|
||||||
await asyncio.sleep(
|
await asyncio.sleep(
|
||||||
random.uniform(
|
random.uniform(
|
||||||
@@ -241,89 +209,24 @@ class MessageSendControl:
|
|||||||
self.message_interval[1]
|
self.message_interval[1]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
message_visualizer.update_content(self.send_temp_container)
|
|
||||||
|
|
||||||
|
async def start_processor(self, bot: Bot):
|
||||||
|
"""启动消息处理器"""
|
||||||
|
self._current_bot = bot
|
||||||
|
|
||||||
async def process_group_queue(self, bot: Bot, group_id: int) -> None:
|
while self._running:
|
||||||
"""处理指定群组的消息队列"""
|
await asyncio.sleep(1.5)
|
||||||
queue = self.send_temp_container.get_queue(group_id)
|
tasks = []
|
||||||
while queue.has_messages():
|
|
||||||
message = queue.get_earliest_message()
|
|
||||||
if message and message.processed_plain_text:
|
|
||||||
await self.send_message(
|
|
||||||
bot=bot,
|
|
||||||
group_id=group_id,
|
|
||||||
content=message.processed_plain_text
|
|
||||||
)
|
|
||||||
queue.update_send_time()
|
|
||||||
|
|
||||||
if queue.has_messages():
|
|
||||||
await asyncio.sleep(
|
|
||||||
random.uniform(self.message_interval[0], self.message_interval[1])
|
|
||||||
)
|
|
||||||
|
|
||||||
async def process_all_queues(self, bot: Bot) -> None:
|
|
||||||
"""处理所有群组的消息队列"""
|
|
||||||
if not self._running or self._paused:
|
|
||||||
return
|
|
||||||
|
|
||||||
for group_id in self.send_temp_container.get_all_groups():
|
for group_id in self.send_temp_container.get_all_groups():
|
||||||
await self.process_group_queue(bot, group_id)
|
tasks.append(self.process_group_messages(group_id))
|
||||||
|
|
||||||
async def send_temp_message(self,
|
# 并行处理所有群组的消息
|
||||||
bot: Bot,
|
await asyncio.gather(*tasks)
|
||||||
group_id: int,
|
message_visualizer.update_content(self.send_temp_container)
|
||||||
message: Union[Message, Message_Thinking],
|
|
||||||
with_emoji: bool = False,
|
|
||||||
emoji_path: Optional[str] = None) -> bool:
|
|
||||||
"""
|
|
||||||
发送单个临时消息
|
|
||||||
Args:
|
|
||||||
bot: Bot实例
|
|
||||||
group_id: 群组ID
|
|
||||||
message: Message对象
|
|
||||||
with_emoji: 是否带表情
|
|
||||||
emoji_path: 表情图片路径
|
|
||||||
Returns:
|
|
||||||
bool: 发送是否成功
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
if with_emoji and emoji_path:
|
|
||||||
return await self.send_with_emoji(
|
|
||||||
bot=bot,
|
|
||||||
group_id=group_id,
|
|
||||||
text_content=message.processed_plain_text,
|
|
||||||
emoji_path=emoji_path
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return await self.send_message(
|
|
||||||
bot=bot,
|
|
||||||
group_id=group_id,
|
|
||||||
content=message.processed_plain_text
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"\033[1;31m[错误]\033[0m 发送临时消息失败: {str(e)}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def set_typing_speed(self, min_speed: float, max_speed: float):
|
def set_typing_speed(self, min_speed: float, max_speed: float):
|
||||||
"""设置打字速度范围"""
|
"""设置打字速度范围"""
|
||||||
self.typing_speed = (min_speed, max_speed)
|
self.typing_speed = (min_speed, max_speed)
|
||||||
|
|
||||||
def set_message_interval(self, min_interval: float, max_interval: float):
|
|
||||||
"""设置消息间隔范围"""
|
|
||||||
self.message_interval = (min_interval, max_interval)
|
|
||||||
|
|
||||||
def pause(self):
|
|
||||||
"""暂停消息处理"""
|
|
||||||
self._paused = True
|
|
||||||
|
|
||||||
def resume(self):
|
|
||||||
"""恢复消息处理"""
|
|
||||||
self._paused = False
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
"""停止消息处理"""
|
|
||||||
self._running = False
|
|
||||||
|
|
||||||
# 创建全局实例
|
# 创建全局实例
|
||||||
message_sender = MessageSendControl()
|
message_sender = MessageSendControl()
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class MessageVisualizer:
|
|||||||
display_text += f"群组: {msg.group_id}\n"
|
display_text += f"群组: {msg.group_id}\n"
|
||||||
display_text += f"用户: {msg.user_nickname}({msg.user_id})\n"
|
display_text += f"用户: {msg.user_nickname}({msg.user_id})\n"
|
||||||
display_text += f"内容: {msg.thinking_text}\n"
|
display_text += f"内容: {msg.thinking_text}\n"
|
||||||
display_text += f"思考时间: {msg.thinking_time}秒\n"
|
display_text += f"思考时间: {int(msg.thinking_time)}秒\n"
|
||||||
else:
|
else:
|
||||||
display_text += f"类型: 普通消息\n"
|
display_text += f"类型: 普通消息\n"
|
||||||
display_text += f"时间: {msg_time}\n"
|
display_text += f"时间: {msg_time}\n"
|
||||||
|
|||||||
@@ -90,17 +90,29 @@ class PromptBuilder:
|
|||||||
if personality_choice < 4/6: # 第一种人格
|
if personality_choice < 4/6: # 第一种人格
|
||||||
prompt_personality = f'''你的网名叫麦麦,是一个学习地质的女大学生,喜欢摄影,你会刷贴吧,你正在浏览qq群,{promt_info_prompt},
|
prompt_personality = f'''你的网名叫麦麦,是一个学习地质的女大学生,喜欢摄影,你会刷贴吧,你正在浏览qq群,{promt_info_prompt},
|
||||||
{activate_prompt}
|
{activate_prompt}
|
||||||
现在请你给出日常且口语化的回复,平淡一些,尽量简短一些,不要输出感叹号。{is_bot_prompt}
|
现在请你给出日常且口语化的回复,平淡一些,尽量简短一些。{is_bot_prompt}
|
||||||
请注意把握群里的聊天内容,不要回复的太有条理,可以有个性。'''
|
请注意把握群里的聊天内容,不要回复的太有条理,可以有个性。'''
|
||||||
elif personality_choice < 1: # 第二种人格
|
elif personality_choice < 1: # 第二种人格
|
||||||
prompt_personality = f'''你的网名叫麦麦,是一个女大学生,你有黑色头发,你会刷小红书, 你正在浏览qq群,{promt_info_prompt},
|
prompt_personality = f'''你的网名叫麦麦,是一个女大学生,你有黑色头发,你会刷小红书, 你正在浏览qq群,{promt_info_prompt},
|
||||||
{activate_prompt}
|
{activate_prompt}
|
||||||
现在请你给出日常且口语化的回复,请表现你自己的见解,不要一昧迎合,尽量简短一些,不要输出感叹号。{is_bot_prompt}
|
现在请你给出日常且口语化的回复,请表现你自己的见解,不要一昧迎合,尽量简短一些。{is_bot_prompt}
|
||||||
请你表达自己的见解和观点。可以有个性。'''
|
请你表达自己的见解和观点。可以有个性。'''
|
||||||
|
|
||||||
|
#中文高手
|
||||||
|
prompt_ger = ''
|
||||||
|
if random.random() < 0.04:
|
||||||
|
prompt_ger += '你喜欢用倒装句'
|
||||||
|
if random.random() < 0.02:
|
||||||
|
prompt_ger += '你喜欢用反问句'
|
||||||
|
if random.random() < 0.01:
|
||||||
|
prompt_ger += '你喜欢用文言文'
|
||||||
|
|
||||||
|
|
||||||
#额外信息要求
|
#额外信息要求
|
||||||
extra_info = '''但是记得回复平淡一些,简短一些,不要过多提及自身的背景, 记住不要输出多余内容(包括前后缀,冒号和引号,括号,表情等),只需要输出回复内容就好,不要输出其他任何内容'''
|
extra_info = '''但是记得回复平淡一些,简短一些,不要过多提及自身的背景, 记住不要输出多余内容(包括前后缀,冒号和引号,括号,表情等),只需要输出回复内容就好,不要输出其他任何内容'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#合并prompt
|
#合并prompt
|
||||||
prompt = ""
|
prompt = ""
|
||||||
# prompt += f"{prompt_info}\n"
|
# prompt += f"{prompt_info}\n"
|
||||||
@@ -108,6 +120,7 @@ class PromptBuilder:
|
|||||||
prompt += f"{chat_talking_prompt}\n"
|
prompt += f"{chat_talking_prompt}\n"
|
||||||
# prompt += f"{activate_prompt}\n"
|
# prompt += f"{activate_prompt}\n"
|
||||||
prompt += f"{prompt_personality}\n"
|
prompt += f"{prompt_personality}\n"
|
||||||
|
prompt += f"{prompt_ger}\n"
|
||||||
prompt += f"{extra_info}\n"
|
prompt += f"{extra_info}\n"
|
||||||
|
|
||||||
return prompt
|
return prompt
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ class Relationship:
|
|||||||
class RelationshipManager:
|
class RelationshipManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.relationships: dict[int, Relationship] = {} # user_id -> Relationship
|
self.relationships: dict[int, Relationship] = {} # user_id -> Relationship
|
||||||
#保存 qq号,现在使用昵称,别称
|
# self.id_name_nickname_table: dict[str, list] = {} # name -> [nickname, nickname, ...]
|
||||||
self.id_name_nickname_table: dict[str, str, list] = {} # name -> [nickname, nickname, ...]
|
# print("[关系管理] 初始化 id_name_nickname_table") # 调试信息
|
||||||
|
|
||||||
async def update_relationship(self, user_id: int, data=None, **kwargs):
|
async def update_relationship(self, user_id: int, data=None, **kwargs):
|
||||||
# 检查是否在内存中已存在
|
# 检查是否在内存中已存在
|
||||||
@@ -67,6 +67,9 @@ class RelationshipManager:
|
|||||||
relationship = Relationship(user_id, data=data) if isinstance(data, dict) else Relationship(user_id, **kwargs)
|
relationship = Relationship(user_id, data=data) if isinstance(data, dict) else Relationship(user_id, **kwargs)
|
||||||
self.relationships[user_id] = relationship
|
self.relationships[user_id] = relationship
|
||||||
|
|
||||||
|
# 更新 id_name_nickname_table
|
||||||
|
# self.id_name_nickname_table[user_id] = [relationship.nickname] # 别称设置为空列表
|
||||||
|
|
||||||
# 保存到数据库
|
# 保存到数据库
|
||||||
await self.storage_relationship(relationship)
|
await self.storage_relationship(relationship)
|
||||||
relationship.saved = True
|
relationship.saved = True
|
||||||
@@ -150,30 +153,11 @@ class RelationshipManager:
|
|||||||
upsert=True
|
upsert=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
def get_name(self, user_id: int) -> str:
|
||||||
async def get_user_nickname(bot: Bot, user_id: int, group_id: int = None) -> Tuple[str, Optional[str]]:
|
if user_id in self.relationships:
|
||||||
"""
|
return self.relationships[user_id].nickname
|
||||||
通过QQ API获取用户昵称
|
else:
|
||||||
"""
|
return "[某人]"
|
||||||
|
|
||||||
# 获取QQ昵称
|
|
||||||
stranger_info = await bot.get_stranger_info(user_id=user_id)
|
|
||||||
qq_nickname = stranger_info['nickname']
|
|
||||||
|
|
||||||
# 如果提供了群号,获取群昵称
|
|
||||||
if group_id:
|
|
||||||
try:
|
|
||||||
member_info = await bot.get_group_member_info(
|
|
||||||
group_id=group_id,
|
|
||||||
user_id=user_id,
|
|
||||||
no_cache=True
|
|
||||||
)
|
|
||||||
group_nickname = member_info['card'] or None
|
|
||||||
return qq_nickname, group_nickname
|
|
||||||
except:
|
|
||||||
return qq_nickname, None
|
|
||||||
|
|
||||||
return qq_nickname, None
|
|
||||||
|
|
||||||
def print_all_relationships(self):
|
def print_all_relationships(self):
|
||||||
"""打印内存中所有的关系记录"""
|
"""打印内存中所有的关系记录"""
|
||||||
@@ -193,8 +177,4 @@ class RelationshipManager:
|
|||||||
print("=" * 50)
|
print("=" * 50)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
relationship_manager = RelationshipManager()
|
relationship_manager = RelationshipManager()
|
||||||
@@ -5,6 +5,8 @@ from .message import Message
|
|||||||
import requests
|
import requests
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from .config import llm_config
|
from .config import llm_config
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
def combine_messages(messages: List[Message]) -> str:
|
def combine_messages(messages: List[Message]) -> str:
|
||||||
"""将消息列表组合成格式化的字符串
|
"""将消息列表组合成格式化的字符串
|
||||||
@@ -115,52 +117,85 @@ def get_recent_group_messages(db, group_id: int, limit: int = 12) -> list:
|
|||||||
message_objects.reverse()
|
message_objects.reverse()
|
||||||
return message_objects
|
return message_objects
|
||||||
|
|
||||||
def split_into_sentences(text: str) -> List[str]:
|
def split_into_sentences_w_remove_punctuation(text: str) -> List[str]:
|
||||||
"""将文本分割成句子,但保持书名号中的内容完整
|
"""将文本分割成句子,但保持书名号中的内容完整
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
text: 要分割的文本字符串
|
text: 要分割的文本字符串
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
List[str]: 分割后的句子列表
|
List[str]: 分割后的句子列表
|
||||||
"""
|
"""
|
||||||
delimiters = ['。', '!', ',', ',', '?', '…', '!', '?', '\n'] # 添加换行符作为分隔符
|
len_text = len(text)
|
||||||
remove_chars = [',', ','] # 只移除这两种逗号
|
if len_text < 5:
|
||||||
sentences = []
|
if random.random() < 0.01:
|
||||||
current_sentence = ""
|
return list(text) # 如果文本很短且触发随机条件,直接按字符分割
|
||||||
in_book_title = False # 标记是否在书名号内
|
else:
|
||||||
|
return [text]
|
||||||
|
if len_text < 12:
|
||||||
|
split_strength = 0.3
|
||||||
|
elif len_text < 32:
|
||||||
|
split_strength = 0.7
|
||||||
|
else:
|
||||||
|
split_strength = 0.9
|
||||||
|
#先移除换行符
|
||||||
|
# print(f"split_strength: {split_strength}")
|
||||||
|
|
||||||
for char in text:
|
# print(f"处理前的文本: {text}")
|
||||||
current_sentence += char
|
|
||||||
|
|
||||||
# 检查书名号
|
# 统一将英文逗号转换为中文逗号
|
||||||
if char == '《':
|
text = text.replace(',', ',')
|
||||||
in_book_title = True
|
text = text.replace('\n', ' ')
|
||||||
elif char == '》':
|
|
||||||
in_book_title = False
|
|
||||||
|
|
||||||
# 只有不在书名号内且是分隔符时才分割
|
# print(f"处理前的文本: {text}")
|
||||||
if char in delimiters and not in_book_title:
|
|
||||||
if current_sentence.strip(): # 确保不是空字符串
|
|
||||||
# 只移除逗号
|
|
||||||
clean_sentence = current_sentence
|
|
||||||
if clean_sentence[-1] in remove_chars:
|
|
||||||
clean_sentence = clean_sentence[:-1]
|
|
||||||
if clean_sentence.strip():
|
|
||||||
sentences.append(clean_sentence.strip())
|
|
||||||
current_sentence = ""
|
|
||||||
|
|
||||||
# 处理最后一个句子
|
text_no_1 = ''
|
||||||
if current_sentence.strip():
|
for letter in text:
|
||||||
# 如果最后一个字符是逗号,移除它
|
# print(f"当前字符: {letter}")
|
||||||
if current_sentence[-1] in remove_chars:
|
if letter in ['!','!','?','?']:
|
||||||
current_sentence = current_sentence[:-1]
|
# print(f"当前字符: {letter}, 随机数: {random.random()}")
|
||||||
sentences.append(current_sentence.strip())
|
if random.random() < split_strength:
|
||||||
|
letter = ''
|
||||||
|
if letter in ['。','…']:
|
||||||
|
# print(f"当前字符: {letter}, 随机数: {random.random()}")
|
||||||
|
if random.random() < 1 - split_strength:
|
||||||
|
letter = ''
|
||||||
|
text_no_1 += letter
|
||||||
|
|
||||||
# 过滤掉空字符串
|
# 对每个逗号单独判断是否分割
|
||||||
sentences = [s for s in sentences if s.strip()]
|
sentences = [text_no_1]
|
||||||
|
new_sentences = []
|
||||||
|
for sentence in sentences:
|
||||||
|
parts = sentence.split(',')
|
||||||
|
current_sentence = parts[0]
|
||||||
|
for part in parts[1:]:
|
||||||
|
if random.random() < split_strength:
|
||||||
|
new_sentences.append(current_sentence.strip())
|
||||||
|
current_sentence = part
|
||||||
|
else:
|
||||||
|
current_sentence += ',' + part
|
||||||
|
# 处理空格分割
|
||||||
|
space_parts = current_sentence.split(' ')
|
||||||
|
current_sentence = space_parts[0]
|
||||||
|
for part in space_parts[1:]:
|
||||||
|
if random.random() < split_strength:
|
||||||
|
new_sentences.append(current_sentence.strip())
|
||||||
|
current_sentence = part
|
||||||
|
else:
|
||||||
|
current_sentence += ' ' + part
|
||||||
|
new_sentences.append(current_sentence.strip())
|
||||||
|
sentences = [s for s in new_sentences if s] # 移除空字符串
|
||||||
|
|
||||||
return sentences
|
# print(f"分割后的句子: {sentences}")
|
||||||
|
sentences_done = []
|
||||||
|
for sentence in sentences:
|
||||||
|
sentence = sentence.rstrip(',,')
|
||||||
|
if random.random() < split_strength*0.5:
|
||||||
|
sentence = sentence.replace(',', '').replace(',', '')
|
||||||
|
elif random.random() < split_strength:
|
||||||
|
sentence = sentence.replace(',', ' ').replace(',', ' ')
|
||||||
|
sentences_done.append(sentence)
|
||||||
|
|
||||||
|
print(f"处理后的句子: {sentences_done}")
|
||||||
|
return sentences_done
|
||||||
|
|
||||||
# 常见的错别字映射
|
# 常见的错别字映射
|
||||||
TYPO_DICT = {
|
TYPO_DICT = {
|
||||||
@@ -259,16 +294,7 @@ def random_remove_punctuation(text: str) -> str:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def add_typos(text: str) -> str:
|
def add_typos(text: str) -> str:
|
||||||
"""随机给文本添加错别字
|
|
||||||
|
|
||||||
Args:
|
|
||||||
text: 要处理的文本
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: 添加错别字后的文本
|
|
||||||
"""
|
|
||||||
TYPO_RATE = 0.02 # 控制错别字出现的概率(2%)
|
TYPO_RATE = 0.02 # 控制错别字出现的概率(2%)
|
||||||
|
|
||||||
result = ""
|
result = ""
|
||||||
for char in text:
|
for char in text:
|
||||||
if char in TYPO_DICT and random.random() < TYPO_RATE:
|
if char in TYPO_DICT and random.random() < TYPO_RATE:
|
||||||
@@ -279,15 +305,33 @@ def add_typos(text: str) -> str:
|
|||||||
result += char
|
result += char
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def process_text_with_typos(text: str) -> str:
|
def process_llm_response(text: str) -> List[str]:
|
||||||
"""处理文本,添加错别字和处理标点符号
|
# processed_response = process_text_with_typos(content)
|
||||||
|
if len(text) > 200:
|
||||||
|
print(f"回复过长 ({len(text)} 字符),返回默认回复")
|
||||||
|
return ['懒得说']
|
||||||
|
# 处理长消息
|
||||||
|
sentences = split_into_sentences_w_remove_punctuation(add_typos(text))
|
||||||
|
# 检查分割后的消息数量是否过多(超过3条)
|
||||||
|
if len(sentences) > 3:
|
||||||
|
print(f"分割后消息数量过多 ({len(sentences)} 条),返回默认回复")
|
||||||
|
return ['麦麦不知道哦']
|
||||||
|
|
||||||
Args:
|
return sentences
|
||||||
text: 要处理的文本
|
|
||||||
|
|
||||||
Returns:
|
def calculate_typing_time(input_string: str, chinese_time: float = 0.2, english_time: float = 0.1) -> float:
|
||||||
str: 处理后的文本
|
|
||||||
"""
|
"""
|
||||||
if random.random() < 0.9: # 90%概率进行处理
|
计算输入字符串所需的时间,中文和英文字符有不同的输入时间
|
||||||
return random_remove_punctuation(add_typos(text))
|
input_string (str): 输入的字符串
|
||||||
return text
|
chinese_time (float): 中文字符的输入时间,默认为0.3秒
|
||||||
|
english_time (float): 英文字符的输入时间,默认为0.15秒
|
||||||
|
"""
|
||||||
|
total_time = 0.0
|
||||||
|
for char in input_string:
|
||||||
|
if '\u4e00' <= char <= '\u9fff': # 判断是否为中文字符
|
||||||
|
total_time += chinese_time
|
||||||
|
else: # 其他字符(如英文)
|
||||||
|
total_time += english_time
|
||||||
|
return total_time
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
7
src/plugins/chat/utils_user.py
Normal file
7
src/plugins/chat/utils_user.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from .relationship_manager import relationship_manager
|
||||||
|
from .config import global_config
|
||||||
|
|
||||||
|
def get_user_nickname(user_id: int) -> str:
|
||||||
|
if user_id == int(global_config.BOT_QQ):
|
||||||
|
return global_config.BOT_NICKNAME
|
||||||
|
return relationship_manager.get_name(user_id)
|
||||||
@@ -27,12 +27,12 @@ class WillingManager:
|
|||||||
current_willing = self.group_reply_willing.get(group_id, 0)
|
current_willing = self.group_reply_willing.get(group_id, 0)
|
||||||
|
|
||||||
if topic and current_willing < 1:
|
if topic and current_willing < 1:
|
||||||
current_willing += 0.4
|
current_willing += 0.3
|
||||||
elif topic:
|
elif topic:
|
||||||
current_willing += 0.05
|
current_willing += 0.05
|
||||||
|
|
||||||
if is_mentioned_bot and current_willing < 1.0:
|
if is_mentioned_bot and current_willing < 1.0:
|
||||||
current_willing += 1
|
current_willing += 0.9
|
||||||
elif is_mentioned_bot:
|
elif is_mentioned_bot:
|
||||||
current_willing += 0.05
|
current_willing += 0.05
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ class WillingManager:
|
|||||||
reply_probability = 0
|
reply_probability = 0
|
||||||
|
|
||||||
if group_id in config.talk_frequency_down_groups:
|
if group_id in config.talk_frequency_down_groups:
|
||||||
reply_probability = reply_probability / 2
|
reply_probability = reply_probability / 3.5
|
||||||
|
|
||||||
if is_mentioned_bot and user_id == int(1026294844):
|
if is_mentioned_bot and user_id == int(1026294844):
|
||||||
reply_probability = 1
|
reply_probability = 1
|
||||||
@@ -62,9 +62,8 @@ class WillingManager:
|
|||||||
def change_reply_willing_after_sent(self, group_id: int):
|
def change_reply_willing_after_sent(self, group_id: int):
|
||||||
"""发送消息后提高群组的回复意愿"""
|
"""发送消息后提高群组的回复意愿"""
|
||||||
current_willing = self.group_reply_willing.get(group_id, 0)
|
current_willing = self.group_reply_willing.get(group_id, 0)
|
||||||
# 如果当前意愿小于1,增加0.3的意愿值
|
|
||||||
if current_willing < 1:
|
if current_willing < 1:
|
||||||
self.group_reply_willing[group_id] = min(1, current_willing + 0.8)
|
self.group_reply_willing[group_id] = min(1, current_willing + 0.4)
|
||||||
|
|
||||||
async def ensure_started(self):
|
async def ensure_started(self):
|
||||||
"""确保衰减任务已启动"""
|
"""确保衰减任务已启动"""
|
||||||
|
|||||||
Reference in New Issue
Block a user