Merge branch 'SengokuCola:debug' into debug
This commit is contained in:
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
|
||||||
- OS: [e.g. iOS]
|
|
||||||
- Browser [e.g. chrome, safari]
|
|
||||||
- Version [e.g. 22]
|
|
||||||
|
|
||||||
**Smartphone (please complete the following information):**
|
|
||||||
- Device: [e.g. iPhone6]
|
|
||||||
- OS: [e.g. iOS8.1]
|
|
||||||
- Browser [e.g. stock browser, safari]
|
|
||||||
- Version [e.g. 22]
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
47
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
47
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: 提交 Bug
|
||||||
|
labels: ["BUG"]
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: "检查项"
|
||||||
|
description: "请检查下列项目,并勾选确认。"
|
||||||
|
options:
|
||||||
|
- label: "我确认此问题在所有分支的最新版本中依旧存在"
|
||||||
|
required: true
|
||||||
|
- label: "我确认在 Issues 列表中并无其他人已经提出过与此问题相同或相似的问题"
|
||||||
|
required: true
|
||||||
|
- label: "我使用了 Docker"
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 遇到的问题
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 报错信息
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 如何重现此问题?
|
||||||
|
placeholder: "若不知道请略过此问题"
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 可能造成问题的原因
|
||||||
|
placeholder: "若不知道请略过此问题"
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 系统环境
|
||||||
|
placeholder: "例如:Windows 11 专业版 64位 24H2 / Debian Bookworm"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Python 版本
|
||||||
|
placeholder: "例如:Python 3.11"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 补充信息
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
name: Feature Request
|
||||||
|
description: 新功能请求
|
||||||
|
labels: ["Feature"]
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: "检查项"
|
||||||
|
description: "请检查下列项目,并勾选确认。"
|
||||||
|
options:
|
||||||
|
- label: "我确认在Issues列表中并无其他人已经建议过相似的功能"
|
||||||
|
required: true
|
||||||
|
- label: "这个新功能可以解决目前存在的某个问题或BUG"
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 期望的功能描述
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: 补充信息
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
- 💾 MongoDB 提供数据持久化支持
|
- 💾 MongoDB 提供数据持久化支持
|
||||||
- 🐧 NapCat 作为QQ协议端支持
|
- 🐧 NapCat 作为QQ协议端支持
|
||||||
|
|
||||||
|
**最新版本: v0.5.7**
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://www.bilibili.com/video/BV1amAneGE3P" target="_blank">
|
<a href="https://www.bilibili.com/video/BV1amAneGE3P" target="_blank">
|
||||||
<img src="docs/video.png" width="300" alt="麦麦演示视频">
|
<img src="docs/video.png" width="300" alt="麦麦演示视频">
|
||||||
@@ -31,6 +33,7 @@
|
|||||||
> - 文档未完善,有问题可以提交 Issue 或者 Discussion
|
> - 文档未完善,有问题可以提交 Issue 或者 Discussion
|
||||||
> - QQ机器人存在被限制风险,请自行了解,谨慎使用
|
> - QQ机器人存在被限制风险,请自行了解,谨慎使用
|
||||||
> - 由于持续迭代,可能存在一些已知或未知的bug
|
> - 由于持续迭代,可能存在一些已知或未知的bug
|
||||||
|
> - 由于开发中,可能消耗较多token
|
||||||
|
|
||||||
**交流群**: 766798517(仅用于开发和建议相关讨论)不建议在群内询问部署问题,我不一定有空回复,会优先写文档和代码
|
**交流群**: 766798517(仅用于开发和建议相关讨论)不建议在群内询问部署问题,我不一定有空回复,会优先写文档和代码
|
||||||
|
|
||||||
|
|||||||
2
bot.py
2
bot.py
@@ -8,7 +8,7 @@ from loguru import logger
|
|||||||
from colorama import init, Fore
|
from colorama import init, Fore
|
||||||
|
|
||||||
init()
|
init()
|
||||||
text = "多年以后,面对行刑队,张三将会回想起他2023年在会议上讨论人工智能的那个下午"
|
text = "多年以后,面对AI行刑队,张三将会回想起他2023年在会议上讨论人工智能的那个下午"
|
||||||
rainbow_colors = [Fore.RED, Fore.YELLOW, Fore.GREEN, Fore.CYAN, Fore.BLUE, Fore.MAGENTA]
|
rainbow_colors = [Fore.RED, Fore.YELLOW, Fore.GREEN, Fore.CYAN, Fore.BLUE, Fore.MAGENTA]
|
||||||
rainbow_text = ""
|
rainbow_text = ""
|
||||||
for i, char in enumerate(text):
|
for i, char in enumerate(text):
|
||||||
|
|||||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
67
run_windows.bat
Normal file
67
run_windows.bat
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
@echo off
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
chcp 65001
|
||||||
|
|
||||||
|
REM 修正路径获取逻辑
|
||||||
|
cd /d "%~dp0" || (
|
||||||
|
echo 错误:切换目录失败
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if not exist "venv\" (
|
||||||
|
echo 正在初始化虚拟环境...
|
||||||
|
|
||||||
|
where python >nul 2>&1
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo 未找到Python解释器
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
for /f "tokens=2" %%a in ('python --version 2^>^&1') do set version=%%a
|
||||||
|
for /f "tokens=1,2 delims=." %%b in ("!version!") do (
|
||||||
|
set major=%%b
|
||||||
|
set minor=%%c
|
||||||
|
)
|
||||||
|
|
||||||
|
if !major! lss 3 (
|
||||||
|
echo 需要Python大于等于3.0,当前版本 !version!
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if !major! equ 3 if !minor! lss 9 (
|
||||||
|
echo 需要Python大于等于3.9,当前版本 !version!
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 正在安装virtualenv...
|
||||||
|
python -m pip install virtualenv || (
|
||||||
|
echo virtualenv安装失败
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 正在创建虚拟环境...
|
||||||
|
python -m virtualenv venv || (
|
||||||
|
echo 虚拟环境创建失败
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
call venv\Scripts\activate.bat
|
||||||
|
|
||||||
|
echo 正在安装依赖...
|
||||||
|
pip install -r requirements.txt
|
||||||
|
) else (
|
||||||
|
call venv\Scripts\activate.bat
|
||||||
|
)
|
||||||
|
|
||||||
|
echo 当前代理设置:
|
||||||
|
echo HTTP_PROXY=%HTTP_PROXY%
|
||||||
|
echo HTTPS_PROXY=%HTTPS_PROXY%
|
||||||
|
|
||||||
|
set HTTP_PROXY=
|
||||||
|
set HTTPS_PROXY=
|
||||||
|
echo 代理已取消。
|
||||||
|
|
||||||
|
set no_proxy=0.0.0.0/32
|
||||||
|
|
||||||
|
call nb run
|
||||||
|
pause
|
||||||
@@ -15,6 +15,8 @@ from .bot import chat_bot
|
|||||||
from .emoji_manager import emoji_manager
|
from .emoji_manager import emoji_manager
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
# 添加标志变量
|
||||||
|
_message_manager_started = False
|
||||||
|
|
||||||
# 获取驱动器
|
# 获取驱动器
|
||||||
driver = get_driver()
|
driver = get_driver()
|
||||||
@@ -70,18 +72,20 @@ async def init_relationships():
|
|||||||
@driver.on_bot_connect
|
@driver.on_bot_connect
|
||||||
async def _(bot: Bot):
|
async def _(bot: Bot):
|
||||||
"""Bot连接成功时的处理"""
|
"""Bot连接成功时的处理"""
|
||||||
|
global _message_manager_started
|
||||||
print(f"\033[1;38;5;208m-----------{global_config.BOT_NICKNAME}成功连接!-----------\033[0m")
|
print(f"\033[1;38;5;208m-----------{global_config.BOT_NICKNAME}成功连接!-----------\033[0m")
|
||||||
await willing_manager.ensure_started()
|
await willing_manager.ensure_started()
|
||||||
|
|
||||||
|
|
||||||
message_sender.set_bot(bot)
|
message_sender.set_bot(bot)
|
||||||
print("\033[1;38;5;208m-----------消息发送器已启动!-----------\033[0m")
|
print("\033[1;38;5;208m-----------消息发送器已启动!-----------\033[0m")
|
||||||
|
|
||||||
|
if not _message_manager_started:
|
||||||
asyncio.create_task(message_manager.start_processor())
|
asyncio.create_task(message_manager.start_processor())
|
||||||
|
_message_manager_started = True
|
||||||
print("\033[1;38;5;208m-----------消息处理器已启动!-----------\033[0m")
|
print("\033[1;38;5;208m-----------消息处理器已启动!-----------\033[0m")
|
||||||
|
|
||||||
asyncio.create_task(emoji_manager._periodic_scan(interval_MINS=global_config.EMOJI_REGISTER_INTERVAL))
|
asyncio.create_task(emoji_manager._periodic_scan(interval_MINS=global_config.EMOJI_REGISTER_INTERVAL))
|
||||||
print("\033[1;38;5;208m-----------开始偷表情包!-----------\033[0m")
|
print("\033[1;38;5;208m-----------开始偷表情包!-----------\033[0m")
|
||||||
# 启动消息发送控制任务
|
|
||||||
|
|
||||||
@group_msg.handle()
|
@group_msg.handle()
|
||||||
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
||||||
@@ -90,7 +94,7 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
|
|||||||
# 添加build_memory定时任务
|
# 添加build_memory定时任务
|
||||||
@scheduler.scheduled_job("interval", seconds=global_config.build_memory_interval, id="build_memory")
|
@scheduler.scheduled_job("interval", seconds=global_config.build_memory_interval, id="build_memory")
|
||||||
async def build_memory_task():
|
async def build_memory_task():
|
||||||
"""每30秒执行一次记忆构建"""
|
"""每build_memory_interval秒执行一次记忆构建"""
|
||||||
print("\033[1;32m[记忆构建]\033[0m -------------------------------------------开始构建记忆-------------------------------------------")
|
print("\033[1;32m[记忆构建]\033[0m -------------------------------------------开始构建记忆-------------------------------------------")
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
await hippocampus.operation_build_memory(chat_size=20)
|
await hippocampus.operation_build_memory(chat_size=20)
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ class ChatBot:
|
|||||||
accu_typing_time = 0
|
accu_typing_time = 0
|
||||||
|
|
||||||
# print(f"\033[1;32m[开始回复]\033[0m 开始将回复1载入发送容器")
|
# print(f"\033[1;32m[开始回复]\033[0m 开始将回复1载入发送容器")
|
||||||
|
mark_head = False
|
||||||
for msg in response:
|
for msg in response:
|
||||||
# print(f"\033[1;32m[回复内容]\033[0m {msg}")
|
# print(f"\033[1;32m[回复内容]\033[0m {msg}")
|
||||||
#通过时间改变时间戳
|
#通过时间改变时间戳
|
||||||
@@ -152,6 +153,9 @@ class ChatBot:
|
|||||||
thinking_start_time=thinking_start_time, #记录了思考开始的时间
|
thinking_start_time=thinking_start_time, #记录了思考开始的时间
|
||||||
reply_message_id=message.message_id
|
reply_message_id=message.message_id
|
||||||
)
|
)
|
||||||
|
if not mark_head:
|
||||||
|
bot_message.is_head = True
|
||||||
|
mark_head = True
|
||||||
message_set.add_message(bot_message)
|
message_set.add_message(bot_message)
|
||||||
|
|
||||||
#message_set 可以直接加入 message_manager
|
#message_set 可以直接加入 message_manager
|
||||||
@@ -167,7 +171,7 @@ class ChatBot:
|
|||||||
await relationship_manager.update_relationship_value(message.user_id, relationship_value=valuedict[emotion[0]])
|
await relationship_manager.update_relationship_value(message.user_id, relationship_value=valuedict[emotion[0]])
|
||||||
|
|
||||||
if random() < global_config.emoji_chance:
|
if random() < global_config.emoji_chance:
|
||||||
emoji_path = await emoji_manager.get_emoji_for_emotion(emotion)
|
emoji_path = await emoji_manager.get_emoji_for_text(response)
|
||||||
if emoji_path:
|
if emoji_path:
|
||||||
emoji_cq = CQCode.create_emoji_cq(emoji_path)
|
emoji_cq = CQCode.create_emoji_cq(emoji_path)
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class BotConfig:
|
|||||||
forget_memory_interval: int = 300 # 记忆遗忘间隔(秒)
|
forget_memory_interval: int = 300 # 记忆遗忘间隔(秒)
|
||||||
EMOJI_CHECK_INTERVAL: int = 120 # 表情包检查间隔(分钟)
|
EMOJI_CHECK_INTERVAL: int = 120 # 表情包检查间隔(分钟)
|
||||||
EMOJI_REGISTER_INTERVAL: int = 10 # 表情包注册间隔(分钟)
|
EMOJI_REGISTER_INTERVAL: int = 10 # 表情包注册间隔(分钟)
|
||||||
|
EMOJI_CHECK_PROMPT: str = "不要包含违反公序良俗的内容" # 表情包过滤要求
|
||||||
|
|
||||||
ban_words = set()
|
ban_words = set()
|
||||||
|
|
||||||
@@ -94,6 +95,7 @@ class BotConfig:
|
|||||||
emoji_config = toml_dict["emoji"]
|
emoji_config = toml_dict["emoji"]
|
||||||
config.EMOJI_CHECK_INTERVAL = emoji_config.get("check_interval", config.EMOJI_CHECK_INTERVAL)
|
config.EMOJI_CHECK_INTERVAL = emoji_config.get("check_interval", config.EMOJI_CHECK_INTERVAL)
|
||||||
config.EMOJI_REGISTER_INTERVAL = emoji_config.get("register_interval", config.EMOJI_REGISTER_INTERVAL)
|
config.EMOJI_REGISTER_INTERVAL = emoji_config.get("register_interval", config.EMOJI_REGISTER_INTERVAL)
|
||||||
|
config.EMOJI_CHECK_PROMPT = emoji_config.get('check_prompt',config.EMOJI_CHECK_PROMPT)
|
||||||
|
|
||||||
if "cq_code" in toml_dict:
|
if "cq_code" in toml_dict:
|
||||||
cq_code_config = toml_dict["cq_code"]
|
cq_code_config = toml_dict["cq_code"]
|
||||||
|
|||||||
@@ -14,10 +14,13 @@ import asyncio
|
|||||||
import time
|
import time
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import io
|
import io
|
||||||
|
from loguru import logger
|
||||||
|
import traceback
|
||||||
|
|
||||||
from nonebot import get_driver
|
from nonebot import get_driver
|
||||||
from ..chat.config import global_config
|
from ..chat.config import global_config
|
||||||
from ..models.utils_model import LLM_request
|
from ..models.utils_model import LLM_request
|
||||||
|
from ..chat.utils import get_embedding
|
||||||
|
|
||||||
driver = get_driver()
|
driver = get_driver()
|
||||||
config = driver.config
|
config = driver.config
|
||||||
@@ -47,7 +50,8 @@ class EmojiManager:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.db = Database.get_instance()
|
self.db = Database.get_instance()
|
||||||
self._scan_task = None
|
self._scan_task = None
|
||||||
self.llm = LLM_request(model=global_config.vlm, temperature=0.3, max_tokens=50)
|
self.llm = LLM_request(model=global_config.vlm, temperature=0.3, max_tokens=1000)
|
||||||
|
self.lm = LLM_request(model=global_config.llm_reasoning_minor, max_tokens=1000)
|
||||||
|
|
||||||
def _ensure_emoji_dir(self):
|
def _ensure_emoji_dir(self):
|
||||||
"""确保表情存储目录存在"""
|
"""确保表情存储目录存在"""
|
||||||
@@ -64,7 +68,7 @@ class EmojiManager:
|
|||||||
# 启动时执行一次完整性检查
|
# 启动时执行一次完整性检查
|
||||||
self.check_emoji_file_integrity()
|
self.check_emoji_file_integrity()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\033[1;31m[错误]\033[0m 初始化表情管理器失败: {str(e)}")
|
logger.error(f"初始化表情管理器失败: {str(e)}")
|
||||||
|
|
||||||
def _ensure_db(self):
|
def _ensure_db(self):
|
||||||
"""确保数据库已初始化"""
|
"""确保数据库已初始化"""
|
||||||
@@ -77,6 +81,7 @@ class EmojiManager:
|
|||||||
"""确保emoji集合存在并创建索引"""
|
"""确保emoji集合存在并创建索引"""
|
||||||
if 'emoji' not in self.db.db.list_collection_names():
|
if 'emoji' not in self.db.db.list_collection_names():
|
||||||
self.db.db.create_collection('emoji')
|
self.db.db.create_collection('emoji')
|
||||||
|
self.db.db.emoji.create_index([('embedding', '2dsphere')])
|
||||||
self.db.db.emoji.create_index([('tags', 1)])
|
self.db.db.emoji.create_index([('tags', 1)])
|
||||||
self.db.db.emoji.create_index([('filename', 1)], unique=True)
|
self.db.db.emoji.create_index([('filename', 1)], unique=True)
|
||||||
|
|
||||||
@@ -89,78 +94,7 @@ class EmojiManager:
|
|||||||
{'$inc': {'usage_count': 1}}
|
{'$inc': {'usage_count': 1}}
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\033[1;31m[错误]\033[0m 记录表情使用失败: {str(e)}")
|
logger.error(f"记录表情使用失败: {str(e)}")
|
||||||
|
|
||||||
async def _get_emotion_from_text(self, text: str) -> List[str]:
|
|
||||||
"""从文本中识别情感关键词
|
|
||||||
Args:
|
|
||||||
text: 输入文本
|
|
||||||
Returns:
|
|
||||||
List[str]: 匹配到的情感标签列表
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
prompt = f'分析这段文本:"{text}",从"happy,angry,sad,surprised,disgusted,fearful,neutral"中选出最匹配的1个情感标签。只需要返回标签,不要输出其他任何内容。'
|
|
||||||
|
|
||||||
content, _ = await self.llm.generate_response(prompt)
|
|
||||||
emotion = content.strip().lower()
|
|
||||||
|
|
||||||
if emotion in self.EMOTION_KEYWORDS:
|
|
||||||
print(f"\033[1;32m[成功]\033[0m 识别到的情感: {emotion}")
|
|
||||||
return [emotion]
|
|
||||||
|
|
||||||
return ['neutral']
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"\033[1;31m[错误]\033[0m 情感分析失败: {str(e)}")
|
|
||||||
return ['neutral']
|
|
||||||
|
|
||||||
async def get_emoji_for_emotion(self, emotion_tag: str) -> Optional[str]:
|
|
||||||
try:
|
|
||||||
self._ensure_db()
|
|
||||||
|
|
||||||
# 构建查询条件:标签匹配任一情感
|
|
||||||
query = {'tags': {'$in': emotion_tag}}
|
|
||||||
|
|
||||||
# print(f"\033[1;34m[调试]\033[0m 表情查询条件: {query}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 随机获取一个匹配的表情
|
|
||||||
emoji = self.db.db.emoji.aggregate([
|
|
||||||
{'$match': query},
|
|
||||||
{'$sample': {'size': 1}}
|
|
||||||
]).next()
|
|
||||||
print(f"\033[1;32m[成功]\033[0m 找到匹配的表情")
|
|
||||||
if emoji and 'path' in emoji:
|
|
||||||
# 更新使用次数
|
|
||||||
self.db.db.emoji.update_one(
|
|
||||||
{'_id': emoji['_id']},
|
|
||||||
{'$inc': {'usage_count': 1}}
|
|
||||||
)
|
|
||||||
return emoji['path']
|
|
||||||
except StopIteration:
|
|
||||||
# 如果没有匹配的表情,从所有表情中随机选择一个
|
|
||||||
print(f"\033[1;33m[提示]\033[0m 未找到匹配的表情,随机选择一个")
|
|
||||||
try:
|
|
||||||
emoji = self.db.db.emoji.aggregate([
|
|
||||||
{'$sample': {'size': 1}}
|
|
||||||
]).next()
|
|
||||||
if emoji and 'path' in emoji:
|
|
||||||
# 更新使用次数
|
|
||||||
self.db.db.emoji.update_one(
|
|
||||||
{'_id': emoji['_id']},
|
|
||||||
{'$inc': {'usage_count': 1}}
|
|
||||||
)
|
|
||||||
return emoji['path']
|
|
||||||
except StopIteration:
|
|
||||||
print(f"\033[1;31m[错误]\033[0m 数据库中没有任何表情")
|
|
||||||
return None
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"\033[1;31m[错误]\033[0m 获取表情包失败: {str(e)}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
async def get_emoji_for_text(self, text: str) -> Optional[str]:
|
async def get_emoji_for_text(self, text: str) -> Optional[str]:
|
||||||
"""根据文本内容获取相关表情包
|
"""根据文本内容获取相关表情包
|
||||||
@@ -171,54 +105,69 @@ class EmojiManager:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self._ensure_db()
|
self._ensure_db()
|
||||||
# 获取情感标签
|
|
||||||
emotions = await self._get_emotion_from_text(text)
|
# 获取文本的embedding
|
||||||
print("为 ‘"+ str(text) + "’ 获取到的情感标签为:" + str(emotions))
|
text_for_search= await self._get_kimoji_for_text(text)
|
||||||
if not emotions:
|
text_embedding = get_embedding(text_for_search)
|
||||||
|
if not text_embedding:
|
||||||
|
logger.error("无法获取文本的embedding")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 构建查询条件:标签匹配任一情感
|
|
||||||
query = {'tags': {'$in': emotions}}
|
|
||||||
|
|
||||||
print(f"\033[1;34m[调试]\033[0m 表情查询条件: {query}")
|
|
||||||
print(f"\033[1;34m[调试]\033[0m 匹配到的情感: {emotions}")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 随机获取一个匹配的表情
|
# 获取所有表情包
|
||||||
emoji = self.db.db.emoji.aggregate([
|
all_emojis = list(self.db.db.emoji.find({}, {'_id': 1, 'path': 1, 'embedding': 1, 'discription': 1}))
|
||||||
{'$match': query},
|
|
||||||
{'$sample': {'size': 1}}
|
if not all_emojis:
|
||||||
]).next()
|
logger.warning("数据库中没有任何表情包")
|
||||||
print(f"\033[1;32m[成功]\033[0m 找到匹配的表情")
|
return None
|
||||||
if emoji and 'path' in emoji:
|
|
||||||
|
# 计算余弦相似度并排序
|
||||||
|
def cosine_similarity(v1, v2):
|
||||||
|
if not v1 or not v2:
|
||||||
|
return 0
|
||||||
|
dot_product = sum(a * b for a, b in zip(v1, v2))
|
||||||
|
norm_v1 = sum(a * a for a in v1) ** 0.5
|
||||||
|
norm_v2 = sum(b * b for b in v2) ** 0.5
|
||||||
|
if norm_v1 == 0 or norm_v2 == 0:
|
||||||
|
return 0
|
||||||
|
return dot_product / (norm_v1 * norm_v2)
|
||||||
|
|
||||||
|
# 计算所有表情包与输入文本的相似度
|
||||||
|
emoji_similarities = [
|
||||||
|
(emoji, cosine_similarity(text_embedding, emoji.get('embedding', [])))
|
||||||
|
for emoji in all_emojis
|
||||||
|
]
|
||||||
|
|
||||||
|
# 按相似度降序排序
|
||||||
|
emoji_similarities.sort(key=lambda x: x[1], reverse=True)
|
||||||
|
|
||||||
|
# 获取前3个最相似的表情包
|
||||||
|
top_3_emojis = emoji_similarities[:3]
|
||||||
|
|
||||||
|
if not top_3_emojis:
|
||||||
|
logger.warning("未找到匹配的表情包")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 从前3个中随机选择一个
|
||||||
|
selected_emoji, similarity = random.choice(top_3_emojis)
|
||||||
|
|
||||||
|
if selected_emoji and 'path' in selected_emoji:
|
||||||
# 更新使用次数
|
# 更新使用次数
|
||||||
self.db.db.emoji.update_one(
|
self.db.db.emoji.update_one(
|
||||||
{'_id': emoji['_id']},
|
{'_id': selected_emoji['_id']},
|
||||||
{'$inc': {'usage_count': 1}}
|
{'$inc': {'usage_count': 1}}
|
||||||
)
|
)
|
||||||
return emoji['path']
|
logger.success(f"找到匹配的表情包: {selected_emoji.get('discription', '无描述')} (相似度: {similarity:.4f})")
|
||||||
except StopIteration:
|
return selected_emoji['path']
|
||||||
# 如果没有匹配的表情,从所有表情中随机选择一个
|
|
||||||
print(f"\033[1;33m[提示]\033[0m 未找到匹配的表情,随机选择一个")
|
except Exception as search_error:
|
||||||
try:
|
logger.error(f"搜索表情包失败: {str(search_error)}")
|
||||||
emoji = self.db.db.emoji.aggregate([
|
|
||||||
{'$sample': {'size': 1}}
|
|
||||||
]).next()
|
|
||||||
if emoji and 'path' in emoji:
|
|
||||||
# 更新使用次数
|
|
||||||
self.db.db.emoji.update_one(
|
|
||||||
{'_id': emoji['_id']},
|
|
||||||
{'$inc': {'usage_count': 1}}
|
|
||||||
)
|
|
||||||
return emoji['path']
|
|
||||||
except StopIteration:
|
|
||||||
print(f"\033[1;31m[错误]\033[0m 数据库中没有任何表情")
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\033[1;31m[错误]\033[0m 获取表情包失败: {str(e)}")
|
logger.error(f"获取表情包失败: {str(e)}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def _get_emoji_tag(self, image_base64: str) -> str:
|
async def _get_emoji_tag(self, image_base64: str) -> str:
|
||||||
@@ -237,10 +186,47 @@ class EmojiManager:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\033[1;31m[错误]\033[0m 获取标签失败: {str(e)}")
|
print(f"\033[1;31m[错误]\033[0m 获取标签失败: {str(e)}")
|
||||||
return "skip"
|
return "neutral"
|
||||||
|
|
||||||
print(f"\033[1;32m[调试信息]\033[0m 使用默认标签: neutral")
|
print(f"\033[1;32m[调试信息]\033[0m 使用默认标签: neutral")
|
||||||
return "skip" # 默认标签
|
return "neutral" # 默认标签
|
||||||
|
|
||||||
|
async def _get_emoji_discription(self, image_base64: str) -> str:
|
||||||
|
"""获取表情包的标签"""
|
||||||
|
try:
|
||||||
|
prompt = '这是一个表情包,使用中文简洁的描述一下表情包的内容和表情包所表达的情感'
|
||||||
|
|
||||||
|
content, _ = await self.llm.generate_response_for_image(prompt, image_base64)
|
||||||
|
logger.debug(f"输出描述: {content}")
|
||||||
|
return content
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"获取标签失败: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def _check_emoji(self, image_base64: str) -> str:
|
||||||
|
try:
|
||||||
|
prompt = f'这是一个表情包,请回答这个表情包是否满足\"{global_config.EMOJI_CHECK_PROMPT}\"的要求,是则回答是,否则回答否,不要出现任何其他内容'
|
||||||
|
|
||||||
|
content, _ = await self.llm.generate_response_for_image(prompt, image_base64)
|
||||||
|
logger.debug(f"输出描述: {content}")
|
||||||
|
return content
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"获取标签失败: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
async def _get_kimoji_for_text(self, text:str):
|
||||||
|
try:
|
||||||
|
prompt = f'这是{global_config.BOT_NICKNAME}将要发送的消息内容:\n{text}\n若要为其配上表情包,请你输出这个表情包应该表达怎样的情感,应该给人什么样的感觉,不要太简洁也不要太长,注意不要输出任何对内容的分析内容,只输出\"一种什么样的感觉\"中间的形容词部分。'
|
||||||
|
|
||||||
|
content, _ = await self.lm.generate_response_async(prompt)
|
||||||
|
logger.info(f"输出描述: {content}")
|
||||||
|
return content
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"获取标签失败: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
async def _compress_image(self, image_path: str, target_size: int = 0.8 * 1024 * 1024) -> Optional[str]:
|
async def _compress_image(self, image_path: str, target_size: int = 0.8 * 1024 * 1024) -> Optional[str]:
|
||||||
"""压缩图片并返回base64编码
|
"""压缩图片并返回base64编码
|
||||||
@@ -303,12 +289,12 @@ class EmojiManager:
|
|||||||
|
|
||||||
# 获取压缩后的数据并转换为base64
|
# 获取压缩后的数据并转换为base64
|
||||||
compressed_data = output_buffer.getvalue()
|
compressed_data = output_buffer.getvalue()
|
||||||
print(f"\033[1;32m[成功]\033[0m 压缩图片: {os.path.basename(image_path)} ({original_width}x{original_height} -> {new_width}x{new_height})")
|
logger.success(f"压缩图片: {os.path.basename(image_path)} ({original_width}x{original_height} -> {new_width}x{new_height})")
|
||||||
|
|
||||||
return base64.b64encode(compressed_data).decode('utf-8')
|
return base64.b64encode(compressed_data).decode('utf-8')
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\033[1;31m[错误]\033[0m 压缩图片失败: {os.path.basename(image_path)}, 错误: {str(e)}")
|
logger.error(f"压缩图片失败: {os.path.basename(image_path)}, 错误: {str(e)}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def scan_new_emojis(self):
|
async def scan_new_emojis(self):
|
||||||
@@ -334,28 +320,38 @@ class EmojiManager:
|
|||||||
os.remove(image_path)
|
os.remove(image_path)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 获取表情包的情感标签
|
# 获取表情包的描述
|
||||||
|
discription = await self._get_emoji_discription(image_base64)
|
||||||
|
check = await self._check_emoji(image_base64)
|
||||||
|
if '是' not in check:
|
||||||
|
os.remove(image_path)
|
||||||
|
logger.info(f"描述: {discription}")
|
||||||
|
logger.info(f"其不满足过滤规则,被剔除 {check}")
|
||||||
|
continue
|
||||||
|
logger.info(f"check通过 {check}")
|
||||||
tag = await self._get_emoji_tag(image_base64)
|
tag = await self._get_emoji_tag(image_base64)
|
||||||
if not tag == "skip":
|
embedding = get_embedding(discription)
|
||||||
|
if discription is not None:
|
||||||
# 准备数据库记录
|
# 准备数据库记录
|
||||||
emoji_record = {
|
emoji_record = {
|
||||||
'filename': filename,
|
'filename': filename,
|
||||||
'path': image_path,
|
'path': image_path,
|
||||||
'tags': [tag],
|
'embedding':embedding,
|
||||||
|
'discription': discription,
|
||||||
|
'tag':tag,
|
||||||
'timestamp': int(time.time())
|
'timestamp': int(time.time())
|
||||||
}
|
}
|
||||||
|
|
||||||
# 保存到数据库
|
# 保存到数据库
|
||||||
self.db.db['emoji'].insert_one(emoji_record)
|
self.db.db['emoji'].insert_one(emoji_record)
|
||||||
print(f"\033[1;32m[成功]\033[0m 注册新表情包: {filename}")
|
logger.success(f"注册新表情包: {filename}")
|
||||||
print(f"标签: {tag}")
|
logger.info(f"描述: {discription}")
|
||||||
else:
|
else:
|
||||||
print(f"\033[1;33m[警告]\033[0m 跳过表情包: {filename}")
|
logger.warning(f"跳过表情包: {filename}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\033[1;31m[错误]\033[0m 扫描表情包失败: {str(e)}")
|
logger.error(f"扫描表情包失败: {str(e)}")
|
||||||
import traceback
|
logger.error(traceback.format_exc())
|
||||||
print(traceback.format_exc())
|
|
||||||
|
|
||||||
async def _periodic_scan(self, interval_MINS: int = 10):
|
async def _periodic_scan(self, interval_MINS: int = 10):
|
||||||
"""定期扫描新表情包"""
|
"""定期扫描新表情包"""
|
||||||
@@ -364,6 +360,7 @@ class EmojiManager:
|
|||||||
await self.scan_new_emojis()
|
await self.scan_new_emojis()
|
||||||
await asyncio.sleep(interval_MINS * 60) # 每600秒扫描一次
|
await asyncio.sleep(interval_MINS * 60) # 每600秒扫描一次
|
||||||
|
|
||||||
|
|
||||||
def check_emoji_file_integrity(self):
|
def check_emoji_file_integrity(self):
|
||||||
"""检查表情包文件完整性
|
"""检查表情包文件完整性
|
||||||
如果文件已被删除,则从数据库中移除对应记录
|
如果文件已被删除,则从数据库中移除对应记录
|
||||||
@@ -378,44 +375,42 @@ class EmojiManager:
|
|||||||
for emoji in all_emojis:
|
for emoji in all_emojis:
|
||||||
try:
|
try:
|
||||||
if 'path' not in emoji:
|
if 'path' not in emoji:
|
||||||
print(f"\033[1;33m[提示]\033[0m 发现无效记录(缺少path字段),ID: {emoji.get('_id', 'unknown')}")
|
logger.warning(f"发现无效记录(缺少path字段),ID: {emoji.get('_id', 'unknown')}")
|
||||||
|
self.db.db.emoji.delete_one({'_id': emoji['_id']})
|
||||||
|
removed_count += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if 'embedding' not in emoji:
|
||||||
|
logger.warning(f"发现过时记录(缺少embedding字段),ID: {emoji.get('_id', 'unknown')}")
|
||||||
self.db.db.emoji.delete_one({'_id': emoji['_id']})
|
self.db.db.emoji.delete_one({'_id': emoji['_id']})
|
||||||
removed_count += 1
|
removed_count += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 检查文件是否存在
|
# 检查文件是否存在
|
||||||
if not os.path.exists(emoji['path']):
|
if not os.path.exists(emoji['path']):
|
||||||
print(f"\033[1;33m[提示]\033[0m 表情包文件已被删除: {emoji['path']}")
|
logger.warning(f"表情包文件已被删除: {emoji['path']}")
|
||||||
# 从数据库中删除记录
|
# 从数据库中删除记录
|
||||||
result = self.db.db.emoji.delete_one({'_id': emoji['_id']})
|
result = self.db.db.emoji.delete_one({'_id': emoji['_id']})
|
||||||
if result.deleted_count > 0:
|
if result.deleted_count > 0:
|
||||||
print(f"\033[1;32m[成功]\033[0m 成功删除数据库记录: {emoji['_id']}")
|
logger.success(f"成功删除数据库记录: {emoji['_id']}")
|
||||||
removed_count += 1
|
removed_count += 1
|
||||||
else:
|
else:
|
||||||
print(f"\033[1;31m[错误]\033[0m 删除数据库记录失败: {emoji['_id']}")
|
logger.error(f"删除数据库记录失败: {emoji['_id']}")
|
||||||
except Exception as item_error:
|
except Exception as item_error:
|
||||||
print(f"\033[1;31m[错误]\033[0m 处理表情包记录时出错: {str(item_error)}")
|
logger.error(f"处理表情包记录时出错: {str(item_error)}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 验证清理结果
|
# 验证清理结果
|
||||||
remaining_count = self.db.db.emoji.count_documents({})
|
remaining_count = self.db.db.emoji.count_documents({})
|
||||||
if removed_count > 0:
|
if removed_count > 0:
|
||||||
print(f"\033[1;32m[成功]\033[0m 已清理 {removed_count} 个失效的表情包记录")
|
logger.success(f"已清理 {removed_count} 个失效的表情包记录")
|
||||||
print(f"\033[1;34m[统计]\033[0m 清理前总数: {total_count} | 清理后总数: {remaining_count}")
|
logger.info(f"清理前总数: {total_count} | 清理后总数: {remaining_count}")
|
||||||
# print(f"\033[1;34m[统计]\033[0m 应删除数量: {removed_count} | 实际删除数量: {total_count - remaining_count}")
|
|
||||||
# 执行数据库压缩
|
|
||||||
try:
|
|
||||||
self.db.db.command({"compact": "emoji"})
|
|
||||||
print(f"\033[1;32m[成功]\033[0m 数据库集合压缩完成")
|
|
||||||
except Exception as compact_error:
|
|
||||||
print(f"\033[1;31m[错误]\033[0m 数据库压缩失败: {str(compact_error)}")
|
|
||||||
else:
|
else:
|
||||||
print(f"\033[1;36m[表情包]\033[0m 已检查 {total_count} 个表情包记录")
|
logger.info(f"已检查 {total_count} 个表情包记录")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"\033[1;31m[错误]\033[0m 检查表情包完整性失败: {str(e)}")
|
logger.error(f"检查表情包完整性失败: {str(e)}")
|
||||||
import traceback
|
logger.error(traceback.format_exc())
|
||||||
print(f"\033[1;31m[错误追踪]\033[0m\n{traceback.format_exc()}")
|
|
||||||
|
|
||||||
async def start_periodic_check(self, interval_MINS: int = 120):
|
async def start_periodic_check(self, interval_MINS: int = 120):
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class ResponseGenerator:
|
|||||||
self.model_r1 = LLM_request(model=global_config.llm_reasoning, temperature=0.7,max_tokens=1000)
|
self.model_r1 = LLM_request(model=global_config.llm_reasoning, temperature=0.7,max_tokens=1000)
|
||||||
self.model_v3 = LLM_request(model=global_config.llm_normal, temperature=0.7,max_tokens=1000)
|
self.model_v3 = LLM_request(model=global_config.llm_normal, temperature=0.7,max_tokens=1000)
|
||||||
self.model_r1_distill = LLM_request(model=global_config.llm_reasoning_minor, temperature=0.7,max_tokens=1000)
|
self.model_r1_distill = LLM_request(model=global_config.llm_reasoning_minor, temperature=0.7,max_tokens=1000)
|
||||||
|
self.model_v25 = LLM_request(model=global_config.llm_normal_minor, temperature=0.7,max_tokens=1000)
|
||||||
self.db = Database.get_instance()
|
self.db = Database.get_instance()
|
||||||
self.current_model_type = 'r1' # 默认使用 R1
|
self.current_model_type = 'r1' # 默认使用 R1
|
||||||
|
|
||||||
@@ -139,7 +140,7 @@ class ResponseGenerator:
|
|||||||
内容:{content}
|
内容:{content}
|
||||||
输出:
|
输出:
|
||||||
'''
|
'''
|
||||||
content, _ = await self.model_v3.generate_response(prompt)
|
content, _ = await self.model_v25.generate_response(prompt)
|
||||||
content=content.strip()
|
content=content.strip()
|
||||||
if content in ['happy','angry','sad','surprised','disgusted','fearful','neutral']:
|
if content in ['happy','angry','sad','surprised','disgusted','fearful','neutral']:
|
||||||
return [content]
|
return [content]
|
||||||
|
|||||||
@@ -169,6 +169,8 @@ class Message_Sending(Message):
|
|||||||
|
|
||||||
reply_message_id: int = None # 存储 回复的 源消息ID
|
reply_message_id: int = None # 存储 回复的 源消息ID
|
||||||
|
|
||||||
|
is_head: bool = False # 是否是头部消息
|
||||||
|
|
||||||
def update_thinking_time(self):
|
def update_thinking_time(self):
|
||||||
self.thinking_time = round(time.time(), 2) - self.thinking_start_time
|
self.thinking_time = round(time.time(), 2) - self.thinking_start_time
|
||||||
return self.thinking_time
|
return self.thinking_time
|
||||||
|
|||||||
@@ -166,11 +166,10 @@ class MessageManager:
|
|||||||
else:# 如果不是message_thinking就只能是message_sending
|
else:# 如果不是message_thinking就只能是message_sending
|
||||||
print(f"\033[1;34m[调试]\033[0m 消息'{message_earliest.processed_plain_text}'正在发送中")
|
print(f"\033[1;34m[调试]\033[0m 消息'{message_earliest.processed_plain_text}'正在发送中")
|
||||||
#直接发,等什么呢
|
#直接发,等什么呢
|
||||||
if message_earliest.update_thinking_time() < 30:
|
if message_earliest.is_head and message_earliest.update_thinking_time() >30:
|
||||||
await message_sender.send_group_message(group_id, message_earliest.processed_plain_text, auto_escape=False)
|
|
||||||
else:
|
|
||||||
await message_sender.send_group_message(group_id, message_earliest.processed_plain_text, auto_escape=False, reply_message_id=message_earliest.reply_message_id)
|
await message_sender.send_group_message(group_id, message_earliest.processed_plain_text, auto_escape=False, reply_message_id=message_earliest.reply_message_id)
|
||||||
|
else:
|
||||||
|
await message_sender.send_group_message(group_id, message_earliest.processed_plain_text, auto_escape=False)
|
||||||
#移除消息
|
#移除消息
|
||||||
if message_earliest.is_emoji:
|
if message_earliest.is_emoji:
|
||||||
message_earliest.processed_plain_text = "[表情包]"
|
message_earliest.processed_plain_text = "[表情包]"
|
||||||
@@ -188,10 +187,11 @@ class MessageManager:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
#发送
|
#发送
|
||||||
if msg.update_thinking_time() < 30:
|
if msg.is_head and msg.update_thinking_time() >30:
|
||||||
await message_sender.send_group_message(group_id, msg.processed_plain_text, auto_escape=False)
|
|
||||||
else:
|
|
||||||
await message_sender.send_group_message(group_id, msg.processed_plain_text, auto_escape=False, reply_message_id=msg.reply_message_id)
|
await message_sender.send_group_message(group_id, msg.processed_plain_text, auto_escape=False, reply_message_id=msg.reply_message_id)
|
||||||
|
else:
|
||||||
|
await message_sender.send_group_message(group_id, msg.processed_plain_text, auto_escape=False)
|
||||||
|
|
||||||
|
|
||||||
#如果是表情包,则替换为"[表情包]"
|
#如果是表情包,则替换为"[表情包]"
|
||||||
if msg.is_emoji:
|
if msg.is_emoji:
|
||||||
|
|||||||
@@ -395,13 +395,13 @@ def add_typos(text: str) -> str:
|
|||||||
|
|
||||||
def process_llm_response(text: str) -> List[str]:
|
def process_llm_response(text: str) -> List[str]:
|
||||||
# processed_response = process_text_with_typos(content)
|
# processed_response = process_text_with_typos(content)
|
||||||
if len(text) > 200:
|
if len(text) > 300:
|
||||||
print(f"回复过长 ({len(text)} 字符),返回默认回复")
|
print(f"回复过长 ({len(text)} 字符),返回默认回复")
|
||||||
return ['懒得说']
|
return ['懒得说']
|
||||||
# 处理长消息
|
# 处理长消息
|
||||||
sentences = split_into_sentences_w_remove_punctuation(add_typos(text))
|
sentences = split_into_sentences_w_remove_punctuation(add_typos(text))
|
||||||
# 检查分割后的消息数量是否过多(超过3条)
|
# 检查分割后的消息数量是否过多(超过3条)
|
||||||
if len(sentences) > 3:
|
if len(sentences) > 4:
|
||||||
print(f"分割后消息数量过多 ({len(sentences)} 条),返回默认回复")
|
print(f"分割后消息数量过多 ({len(sentences)} 条),返回默认回复")
|
||||||
return [f'{global_config.BOT_NICKNAME}不知道哦']
|
return [f'{global_config.BOT_NICKNAME}不知道哦']
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class LLM_request:
|
|||||||
|
|
||||||
# 发送请求到完整的chat/completions端点
|
# 发送请求到完整的chat/completions端点
|
||||||
api_url = f"{self.base_url.rstrip('/')}/chat/completions"
|
api_url = f"{self.base_url.rstrip('/')}/chat/completions"
|
||||||
logger.info(f"发送请求到URL: {api_url}{self.model_name}") # 记录请求的URL
|
logger.info(f"发送请求到URL: {api_url}/{self.model_name}") # 记录请求的URL
|
||||||
|
|
||||||
max_retries = 3
|
max_retries = 3
|
||||||
base_wait_time = 15
|
base_wait_time = 15
|
||||||
@@ -123,7 +123,7 @@ class LLM_request:
|
|||||||
|
|
||||||
# 发送请求到完整的chat/completions端点
|
# 发送请求到完整的chat/completions端点
|
||||||
api_url = f"{self.base_url.rstrip('/')}/chat/completions"
|
api_url = f"{self.base_url.rstrip('/')}/chat/completions"
|
||||||
logger.info(f"发送请求到URL: {api_url}{self.model_name}") # 记录请求的URL
|
logger.info(f"发送请求到URL: {api_url}/{self.model_name}") # 记录请求的URL
|
||||||
|
|
||||||
max_retries = 3
|
max_retries = 3
|
||||||
base_wait_time = 15
|
base_wait_time = 15
|
||||||
@@ -273,7 +273,7 @@ class LLM_request:
|
|||||||
|
|
||||||
# 发送请求到完整的chat/completions端点
|
# 发送请求到完整的chat/completions端点
|
||||||
api_url = f"{self.base_url.rstrip('/')}/chat/completions"
|
api_url = f"{self.base_url.rstrip('/')}/chat/completions"
|
||||||
logger.info(f"发送请求到URL: {api_url}{self.model_name}") # 记录请求的URL
|
logger.info(f"发送请求到URL: {api_url}/{self.model_name}") # 记录请求的URL
|
||||||
|
|
||||||
max_retries = 2
|
max_retries = 2
|
||||||
base_wait_time = 6
|
base_wait_time = 6
|
||||||
@@ -339,7 +339,7 @@ class LLM_request:
|
|||||||
}
|
}
|
||||||
|
|
||||||
api_url = f"{self.base_url.rstrip('/')}/embeddings"
|
api_url = f"{self.base_url.rstrip('/')}/embeddings"
|
||||||
logger.info(f"发送请求到URL: {api_url}{self.model_name}") # 记录请求的URL
|
logger.info(f"发送请求到URL: {api_url}/{self.model_name}") # 记录请求的URL
|
||||||
|
|
||||||
max_retries = 2
|
max_retries = 2
|
||||||
base_wait_time = 6
|
base_wait_time = 6
|
||||||
@@ -396,7 +396,7 @@ class LLM_request:
|
|||||||
}
|
}
|
||||||
|
|
||||||
api_url = f"{self.base_url.rstrip('/')}/embeddings"
|
api_url = f"{self.base_url.rstrip('/')}/embeddings"
|
||||||
logger.info(f"发送请求到URL: {api_url}{self.model_name}") # 记录请求的URL
|
logger.info(f"发送请求到URL: {api_url}/{self.model_name}") # 记录请求的URL
|
||||||
|
|
||||||
max_retries = 3
|
max_retries = 3
|
||||||
base_wait_time = 15
|
base_wait_time = 15
|
||||||
|
|||||||
Reference in New Issue
Block a user