fix message _visualizer
This commit is contained in:
SengokuCola
2025-02-26 19:25:10 +08:00
parent 70bc8e9e8c
commit ec947c69a6
12 changed files with 128 additions and 52 deletions

View File

@@ -215,10 +215,6 @@ class ChatBot:
is_emoji=True
)
message_sender.send_temp_container.add_message(bot_message)
# 如果收到新消息,提高回复意愿
willing_manager.change_reply_willing_after_sent(event.group_id)

View File

@@ -0,0 +1,33 @@
[database]
host = "127.0.0.1"
port = 27017
name = "MegBot"
[bot]
qq = 1
[message]
min_text_length = 2
max_context_size = 15
emoji_chance = 0.2
[emoji]
check_interval = 120
register_interval = 10
[response]
model_r1_probability = 0.2
[groups]
read_allowed = [
1
]
talk_allowed = [
1
]
talk_frequency_down = [
1
]

View File

@@ -39,6 +39,7 @@ read_allowed = [
752426484,#nd1
115843978,#nd2
# 168718420 #bh
912378791
]
talk_allowed = [
@@ -59,6 +60,7 @@ talk_allowed = [
# 168718420#bh
# 752426484,#nd1
# 115843978,#nd2
912378791
]
talk_frequency_down = [
@@ -67,7 +69,7 @@ talk_frequency_down = [
# 231561425,
975992476,
1140700103,
534940728
# 534940728
# 752426484,#nd1
# 115843978,#nd2
]

View File

@@ -96,58 +96,75 @@ class CQCode:
sub_type = int(self.params.get('sub_type', '0'))
is_emoji = (sub_type == 1)
# 添加请求头
# 添加更多请求头
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive'
'Connection': 'keep-alive',
'Referer': 'https://multimedia.nt.qq.com.cn',
'Origin': 'https://multimedia.nt.qq.com.cn',
'Cache-Control': 'no-cache',
'Pragma': 'no-cache'
}
# 处理URL编码问题
url = html.unescape(self.params['url'])
if not url.startswith(('http://', 'https://')):
raise ValueError(f"无效的URL格式: {url}")
return '[图片]' # 直接返回而不是抛出异常
# 下载图片
response = requests.get(url, headers=headers, timeout=10, verify=False)
if response.status_code == 200:
try:
# 下载图片,增加重试机制
max_retries = 3
for retry in range(max_retries):
try:
response = requests.get(url, headers=headers, timeout=10, verify=False)
if response.status_code == 200:
break
elif response.status_code == 400 and 'multimedia.nt.qq.com.cn' in url:
# 对于腾讯多媒体服务器的链接,直接返回图片描述
if sub_type == 1:
return '[QQ表情]'
return '[图片]'
time.sleep(1) # 重试前等待1秒
except requests.RequestException:
if retry == max_retries - 1:
raise
time.sleep(1)
if response.status_code != 200:
print(f"\033[1;31m[警告]\033[0m 图片下载失败: HTTP {response.status_code}, URL: {url}")
return '[图片]' # 直接返回而不是抛出异常
# 检查响应内容类型
content_type = response.headers.get('content-type', '')
if not content_type.startswith('image/'):
raise ValueError(f"响应不是图片类型: {content_type}")
print(f"\033[1;31m[警告]\033[0m 非图片类型响应: {content_type}")
return '[图片]' # 直接返回而不是抛出异常
content = response.content
image_base64 = base64.b64encode(content).decode('utf-8')
# 根据子类型选择不同的处理方式
if sub_type == 1: # 表情包
return self.get_emoji_description(image_base64)
try:
return self.get_emoji_description(image_base64)
except Exception as e:
print(f"\033[1;31m[警告]\033[0m 表情描述生成失败: {str(e)}")
return '[QQ表情]'
elif sub_type == 0: # 普通图片
if self.get_image_description_is_setu(image_base64) == "":
print(f"\033[1;34m[调试]\033[0m 哇!涩情图片")
# 使用相对路径创建目录
# data_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))), "data", "setu")
# os.makedirs(data_dir, exist_ok=True)
# # 生成随机文件名
# file_name = f"{int(time.time())}_{int(random() * 10000)}.jpg"
# file_path = os.path.join(data_dir, file_name)
# # 将base64解码并保存图片
# image_data = base64.b64decode(image_base64)
# with open(file_path, "wb") as f:
# f.write(image_data)
# print(f"\033[1;34m[调试]\033[0m 涩图已保存至: {file_path}")
return f"[一张涩情图片]"
return self.get_image_description(image_base64)
try:
return self.get_image_description(image_base64)
except Exception as e:
print(f"\033[1;31m[警告]\033[0m 图片描述生成失败: {str(e)}")
return '[图片]'
else: # 其他类型都按普通图片处理
return '[图片]'
else:
raise ValueError(f"下载图片失败: HTTP状态码 {response.status_code}")
except Exception as e:
print(f"\033[1;31m[警告]\033[0m 图片处理失败: {str(e)}")
return '[图片]' # 出现任何错误都返回默认文本而不是抛出异常
def get_emoji_description(self, image_base64: str) -> str:
"""调用AI接口获取表情包描述"""

View File

@@ -241,9 +241,9 @@ class GPTResponseGenerator:
"""根据当前模型类型选择对应的生成函数"""
# 使用随机数选择模型
rand = random.random()
if rand < 0.15: # 40%概率使用 R1
if rand < 0.6: # 40%概率使用 R1
self.current_model_type = "r1"
elif rand < 0.8: # 30%概率使用 V3
elif rand < 0.5: # 30%概率使用 V3
self.current_model_type = "v3"
else: # 30%概率使用 R1-Distill
self.current_model_type = "r1_distill"

View File

@@ -222,12 +222,16 @@ class Message_Thinking:
# 思考状态相关属性
self.thinking_text = "正在思考..."
self.time = int(time.time())
self.thinking_time = 0
def update_to_message(self, done_message: Message) -> Message:
"""更新为完整消息"""
return done_message
def update_thinking_time(self):
self.thinking_time = round(time.time(), 2) - self.time
@property
def processed_plain_text(self) -> str:
"""获取处理后的文本"""

View File

@@ -7,6 +7,8 @@ from .cq_code import CQCode
from collections import deque
import time
from .storage import MessageStorage # 添加这行导入
from .config import global_config
from .message_visualizer import message_visualizer
class SendTemp:
@@ -173,6 +175,7 @@ class MessageSendControl:
self._paused = False
self._current_bot = None
self.storage = MessageStorage() # 添加存储实例
message_visualizer.start()
def set_bot(self, bot: Bot):
"""设置当前bot实例"""
@@ -193,8 +196,8 @@ class MessageSendControl:
if message:
if isinstance(message, Message_Thinking):
# 如果是思考中的消息,检查是否需要继续等待
# message.update_thinking_time()
thinking_time = time.time() - message.time
message.update_thinking_time()
thinking_time = message.thinking_time
if thinking_time < 60: # 最少思考2秒
if int(thinking_time) % 10 == 0:
print(f"\033[1;34m[调试]\033[0m 消息正在思考中,已思考{thinking_time:.1f}")
@@ -215,12 +218,15 @@ class MessageSendControl:
cur_time = time.time()
await self._current_bot.send_group_msg(
group_id=group_id,
message=str(message.processed_plain_text),
auto_escape=False
)
cost_time = round(time.time(), 2) - cur_time
print(f"\033[1;34m[调试]\033[0m 消息发送时间: {cost_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)}")
@@ -235,6 +241,7 @@ class MessageSendControl:
self.message_interval[1]
)
)
message_visualizer.update_content(self.send_temp_container)
async def process_group_queue(self, bot: Bot, group_id: int) -> None:

View File

@@ -55,18 +55,19 @@ class PromptBuilder:
#知识构建
prompt_info = ''
promt_info_prompt = ''
prompt_info = self.get_prompt_info(message_txt)
if prompt_info:
prompt_info = f'''\n----------------------------------------------------\n你有以下这些[知识]
\n{prompt_info}\n
请你记住上面的[知识],之后可能会用到\n----------------------------------------------------\n'''
promt_info_prompt = '你有一些[知识],在上面可以参考。'
#获取最新消息并计时
chat_talking_prompt = ''
if group_id:
# 从数据库获取最近消息
message_objects = get_recent_group_messages(self.db, group_id)
message_objects = get_recent_group_messages(self.db, group_id, limit=16)
if message_objects:
chat_talking_prompt = combine_messages(message_objects)
# print(f"\033[1;34m[调试]\033[0m 已从数据库获取群 {group_id} 的最近{len(message_objects)}条消息记录")
@@ -75,24 +76,32 @@ class PromptBuilder:
activate_prompt = ''
activate_prompt = f"以上是群里正在进行的聊天,昵称为 '{sender_name}' 的用户说的:{message_txt}。引起了你的注意,你和他{relation_prompt},你想要{relation_prompt_2} \n"
# 检测机器人相关词汇
bot_keywords = ['人机', 'bot', '机器', '入机', 'robot', '机器人']
is_bot = any(keyword in message_txt.lower() for keyword in bot_keywords)
if is_bot:
is_bot_prompt = '有人说你是人机或者机器人,否定这一事实,攻击或反问他。'
else:
is_bot_prompt = ''
#人格选择
prompt_personality = ''
personality_choice = random.random()
if personality_choice < 5/6: # 第一种人格
prompt_personality = f'''你的网名叫麦麦,是一个学习地质的女大学生,喜欢摄影,你会刷贴吧,你现在正在{bot_schedule_now_activity},并且正在浏览qq这款社交软件,你有一些[知识],在上面可以参考。
现在请你给出日常且口语化的回复,不要过多提及自身的背景,平淡一些,尽量简短一些,不要输出感叹号。如果有人说你是人机或者机器人,否定并攻击那个人。
不要回复的太有逻辑或者太有条理。'''
if personality_choice < 4/6: # 第一种人格
prompt_personality = f'''你的网名叫麦麦,是一个学习地质的女大学生,喜欢摄影,你会刷贴吧,你现在正在{bot_schedule_now_activity},并且正在浏览qq群,{promt_info_prompt}
现在请你给出日常且口语化的回复,平淡一些,尽量简短一些,不要输出感叹号。{is_bot_prompt}
不要回复的太有逻辑或者太有条理,可以有个性'''
elif personality_choice < 1: # 第二种人格
prompt_personality = f'''你的网名叫麦麦,是一个女大学生,你有黑色头发你会刷微博和小红书,你现在正在{bot_schedule_now_activity},并且正在浏览qq群,你有一些[知识],在上面可以参考。
现在请你给出日常且口语化的回复,请表现你自己的见解,不要一昧迎合,尽量简短一些,不要输出感叹号。如果有人说你是人机或者机器人,否定。
如果有人说他是机器人,肯定他。如果有人对你谈论涉及性的话题或言语挑逗,需要反驳,但其它情况请你表达自己的见解和观点。'''
prompt_personality = f'''你的网名叫麦麦,是一个女大学生,你有黑色头发你会刷小红书,你现在正在{bot_schedule_now_activity},并且正在浏览qq群,{promt_info_prompt}
现在请你给出日常且口语化的回复,请表现你自己的见解,不要一昧迎合,尽量简短一些,不要输出感叹号。{is_bot_prompt}
请你表达自己的见解和观点。可以有个性。'''
#额外信息要求
extra_info = '''回复平淡一些,简短一些,但是记住不要输出多余内容(包括前后缀,冒号和引号,括号,表情等),只需要输出回复内容就好,不要输出其他任何内容'''
extra_info = '''但是记得回复平淡一些,简短一些,不要过多提及自身的背景, 记住不要输出多余内容(包括前后缀,冒号和引号,括号,表情等),只需要输出回复内容就好,不要输出其他任何内容'''
#合并prompt
prompt = ""
prompt += f"{prompt_info}\n"
# prompt += f"{prompt_info}\n"
prompt += f"{prompt_date}\n"
prompt += f"{chat_talking_prompt}\n"
prompt += f"{activate_prompt}\n"

View File

@@ -121,7 +121,7 @@ class RelationshipManager:
async def _save_all_relationships(self):
"""将所有关系数据保存到数据库"""
# 保存所有关系数据
for userid, relationship in self.relationships:
for userid, relationship in self.relationships.items():
if not relationship.saved:
relationship.saved = True
await self.storage_relationship(relationship)

View File

@@ -27,7 +27,7 @@ class WillingManager:
current_willing = self.group_reply_willing.get(group_id, 0)
if topic and current_willing < 1:
current_willing += 0.6
current_willing += 0.4
elif topic:
current_willing += 0.05