From e0240d652b6deb19ebb4e92b0a97c5b302e5c20f Mon Sep 17 00:00:00 2001 From: infinitycat Date: Wed, 2 Apr 2025 10:50:27 +0800 Subject: [PATCH 01/16] =?UTF-8?q?refactor(infrastructure):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20Docker=20Compose=20=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 adapters、MaiMBot、mongodb 和 napcat 的数据卷挂载路径 - 统一使用 ./docker-config 目录结构进行配置文件和数据持久化 -移除冗余的配置项,简化配置结构 --- docker-compose.yml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7b4fcd2d..8e1edf76 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,8 +7,8 @@ services: ports: - "18002:18002" volumes: - - ./adapters/plugins:/adapters/src/plugins # 持久化adapters插件 - - ./adapters/.env:/adapters/.env # 持久化adapters配置文件 + - ./docker-config/adapters/plugins:/adapters/src/plugins # 持久化adapters + - ./docker-config/adapters/.env:/adapters/.env # 持久化adapters配置文件 - ./data/qq:/app/.config/QQ # 持久化QQ本体并同步qq表情和图片到adapters restart: always depends_on: @@ -25,9 +25,8 @@ services: ports: - "8000:8000" volumes: - - ./mmc-data:/MaiMBot/data - - ./mmc-config/.env:/MaiMBot/.env # 持久化bot配置文件 - - ./mmc-config/bot_config.toml:/MaiMBot/config/bot_config.toml # 持久化bot配置文件 + - ./docker-config/mmc/.env:/MaiMBot/.env # 持久化env配置文件 + - ./docker-config/mmc:/MaiMBot/config # 持久化bot配置文件 - ./data/MaiMBot:/MaiMBot/data # NapCat 和 NoneBot 共享此卷,否则发送图片会有问题 restart: always depends_on: @@ -45,7 +44,7 @@ services: restart: always volumes: - mongodb:/data/db # 持久化mongodb数据 - - mongodbCONFIG:/data/configdb # 持久化mongodb配置文件 + - ./docker-config/mongodb:/data/configdb # 持久化mongodb配置文件 image: mongo:latest networks: - maim_bot @@ -58,7 +57,7 @@ services: - "6099:6099" - "8095:8095" volumes: - - ./napcat-config:/app/napcat/config # 持久化napcat配置文件 + - ./docker-config/napcat:/app/napcat/config # 持久化napcat配置文件 - ./data/qq:/app/.config/QQ # 持久化QQ本体并同步qq表情和图片到adapters - ./data/MaiMBot:/MaiMBot/data # NapCat 和 NoneBot 共享此卷,否则发送图片会有问题 container_name: maim-bot-napcat @@ -70,5 +69,4 @@ networks: maim_bot: driver: bridge volumes: - mongodb: - mongodbCONFIG: \ No newline at end of file + mongodb: \ No newline at end of file From 4197ce5906ad57d179e18fdbc4d60b376f99d035 Mon Sep 17 00:00:00 2001 From: infinitycat Date: Wed, 2 Apr 2025 12:51:26 +0800 Subject: [PATCH 02/16] =?UTF-8?q?vol(mongodb):=20=E4=BF=AE=E6=94=B9=20Mong?= =?UTF-8?q?oDB=20=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E6=8C=81=E4=B9=85?= =?UTF-8?q?=E5=8C=96=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -将本地路径 ./docker-config/mongodb 更改为使用自定义卷 mongodbCONFIG - 在 volumes 部分添加 mongodbCONFIG 卷的定义 --- docker-compose.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 8e1edf76..cf35ffec 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -44,7 +44,7 @@ services: restart: always volumes: - mongodb:/data/db # 持久化mongodb数据 - - ./docker-config/mongodb:/data/configdb # 持久化mongodb配置文件 + - mongodbCONFIG:/data/configdb # 持久化mongodb配置文件 image: mongo:latest networks: - maim_bot @@ -69,4 +69,5 @@ networks: maim_bot: driver: bridge volumes: - mongodb: \ No newline at end of file + mongodb: + mongodbCONFIG: \ No newline at end of file From 33f41be6feb43de250cab81cf9f0afb2af633452 Mon Sep 17 00:00:00 2001 From: Cookie987 Date: Wed, 2 Apr 2025 14:38:00 +0800 Subject: [PATCH 03/16] =?UTF-8?q?MaiCore&Nonebot=20adapter=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.sh | 816 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 816 insertions(+) create mode 100644 run.sh diff --git a/run.sh b/run.sh new file mode 100644 index 00000000..6e95ab9e --- /dev/null +++ b/run.sh @@ -0,0 +1,816 @@ +#!/bin/bash + +<<<<<<< Updated upstream +# 麦麦Bot一键安装脚本 by Cookie_987 +# 适用于Arch/Ubuntu 24.10/Debian 12/CentOS 9 +# 请小心使用任何一键脚本! + +INSTALLER_VERSION="0.0.3" +LANG=C.UTF-8 + +# 如无法访问GitHub请修改此处镜像地址 +GITHUB_REPO="https://ghfast.top/https://github.com/SengokuCola/MaiMBot.git" +======= +# MaiCore & Nonebot adapter一键安装脚本 by Cookie_987 +# 适用于Arch/Ubuntu 24.10/Debian 12/CentOS 9 +# 请小心使用任何一键脚本! + +INSTALLER_VERSION="0.0.1-refactor" +LANG=C.UTF-8 + +# 如无法访问GitHub请修改此处镜像地址 +GITHUB_REPO="https://github.com/MaiM-with-u/MaiBot.git" +>>>>>>> Stashed changes + +# 颜色输出 +GREEN="\e[32m" +RED="\e[31m" +RESET="\e[0m" + +# 需要的基本软件包 + +declare -A REQUIRED_PACKAGES=( + ["common"]="git sudo python3 curl gnupg" + ["debian"]="python3-venv python3-pip" + ["ubuntu"]="python3-venv python3-pip" + ["centos"]="python3-pip" + ["arch"]="python-virtualenv python-pip" +) + +# 默认项目目录 +DEFAULT_INSTALL_DIR="/opt/maimbot" + +# 服务名称 +<<<<<<< Updated upstream +SERVICE_NAME="maimbot-daemon" +SERVICE_NAME_WEB="maimbot-web" +======= +SERVICE_NAME="maicore" +SERVICE_NAME_WEB="maicore-web" +SERVICE_NAME_NBADAPTER="maicore-nonebot-adapter" +>>>>>>> Stashed changes + +IS_INSTALL_MONGODB=false +IS_INSTALL_NAPCAT=false +IS_INSTALL_DEPENDENCIES=false + +# 检查是否已安装 +check_installed() { + [[ -f /etc/systemd/system/${SERVICE_NAME}.service ]] +} + +# 加载安装信息 +load_install_info() { +<<<<<<< Updated upstream + if [[ -f /etc/maimbot_install.conf ]]; then + source /etc/maimbot_install.conf + else + INSTALL_DIR="$DEFAULT_INSTALL_DIR" + BRANCH="main" +======= + if [[ -f /etc/maicore_install.conf ]]; then + source /etc/maicore_install.conf + else + INSTALL_DIR="$DEFAULT_INSTALL_DIR" + BRANCH="refactor" +>>>>>>> Stashed changes + fi +} + +# 显示管理菜单 +show_menu() { + while true; do +<<<<<<< Updated upstream + choice=$(whiptail --title "麦麦Bot管理菜单" --menu "请选择要执行的操作:" 15 60 7 \ + "1" "启动麦麦Bot" \ + "2" "停止麦麦Bot" \ + "3" "重启麦麦Bot" \ + "4" "启动WebUI" \ + "5" "停止WebUI" \ + "6" "重启WebUI" \ + "7" "更新麦麦Bot及其依赖" \ + "8" "切换分支" \ + "9" "更新配置文件" \ + "10" "退出" 3>&1 1>&2 2>&3) +======= + choice=$(whiptail --title "MaiCore管理菜单" --menu "请选择要执行的操作:" 15 60 7 \ + "1" "启动MaiCore" \ + "2" "停止MaiCore" \ + "3" "重启MaiCore" \ + "4" "启动Nonebot adapter" \ + "5" "停止Nonebot adapter" \ + "6" "重启Nonebot adapter" \ + "7" "更新MaiCore及其依赖" \ + "8" "切换分支" \ + "9" "退出" 3>&1 1>&2 2>&3) +>>>>>>> Stashed changes + + [[ $? -ne 0 ]] && exit 0 + + case "$choice" in + 1) + systemctl start ${SERVICE_NAME} +<<<<<<< Updated upstream + whiptail --msgbox "✅麦麦Bot已启动" 10 60 + ;; + 2) + systemctl stop ${SERVICE_NAME} + whiptail --msgbox "🛑麦麦Bot已停止" 10 60 + ;; + 3) + systemctl restart ${SERVICE_NAME} + whiptail --msgbox "🔄麦麦Bot已重启" 10 60 + ;; + 4) + systemctl start ${SERVICE_NAME_WEB} + whiptail --msgbox "✅WebUI已启动" 10 60 + ;; + 5) + systemctl stop ${SERVICE_NAME_WEB} + whiptail --msgbox "🛑WebUI已停止" 10 60 + ;; + 6) + systemctl restart ${SERVICE_NAME_WEB} + whiptail --msgbox "🔄WebUI已重启" 10 60 +======= + whiptail --msgbox "✅MaiCore已启动" 10 60 + ;; + 2) + systemctl stop ${SERVICE_NAME} + whiptail --msgbox "🛑MaiCore已停止" 10 60 + ;; + 3) + systemctl restart ${SERVICE_NAME} + whiptail --msgbox "🔄MaiCore已重启" 10 60 + ;; + 4) + systemctl start ${SERVICE_NAME_NBADAPTER} + whiptail --msgbox "✅Nonebot adapter已启动" 10 60 + ;; + 5) + systemctl stop ${SERVICE_NAME_NBADAPTER} + whiptail --msgbox "🛑Nonebot adapter已停止" 10 60 + ;; + 6) + systemctl restart ${SERVICE_NAME_NBADAPTER} + whiptail --msgbox "🔄Nonebot adapter已重启" 10 60 +>>>>>>> Stashed changes + ;; + 7) + update_dependencies + ;; + 8) + switch_branch + ;; + 9) +<<<<<<< Updated upstream + update_config + ;; + 10) +======= +>>>>>>> Stashed changes + exit 0 + ;; + *) + whiptail --msgbox "无效选项!" 10 60 + ;; + esac + done +} + +# 更新依赖 +update_dependencies() { +<<<<<<< Updated upstream + cd "${INSTALL_DIR}/repo" || { +======= + cd "${INSTALL_DIR}/MaiBot" || { +>>>>>>> Stashed changes + whiptail --msgbox "🚫 无法进入安装目录!" 10 60 + return 1 + } + if ! git pull origin "${BRANCH}"; then + whiptail --msgbox "🚫 代码更新失败!" 10 60 + return 1 + fi + source "${INSTALL_DIR}/venv/bin/activate" + if ! pip install -r requirements.txt; then + whiptail --msgbox "🚫 依赖安装失败!" 10 60 + deactivate + return 1 + fi + deactivate + systemctl restart ${SERVICE_NAME} + whiptail --msgbox "✅ 依赖已更新并重启服务!" 10 60 +} + +# 切换分支 +switch_branch() { + new_branch=$(whiptail --inputbox "请输入要切换的分支名称:" 10 60 "${BRANCH}" 3>&1 1>&2 2>&3) + [[ -z "$new_branch" ]] && { + whiptail --msgbox "🚫 分支名称不能为空!" 10 60 + return 1 + } + +<<<<<<< Updated upstream + cd "${INSTALL_DIR}/repo" || { +======= + cd "${INSTALL_DIR}/MaiBot" || { +>>>>>>> Stashed changes + whiptail --msgbox "🚫 无法进入安装目录!" 10 60 + return 1 + } + + if ! git ls-remote --exit-code --heads origin "${new_branch}" >/dev/null 2>&1; then + whiptail --msgbox "🚫 分支 ${new_branch} 不存在!" 10 60 + return 1 + fi + + if ! git checkout "${new_branch}"; then + whiptail --msgbox "🚫 分支切换失败!" 10 60 + return 1 + fi + + if ! git pull origin "${new_branch}"; then + whiptail --msgbox "🚫 代码拉取失败!" 10 60 + return 1 + fi + + source "${INSTALL_DIR}/venv/bin/activate" + pip install -r requirements.txt + deactivate + +<<<<<<< Updated upstream + sed -i "s/^BRANCH=.*/BRANCH=${new_branch}/" /etc/maimbot_install.conf +======= + sed -i "s/^BRANCH=.*/BRANCH=${new_branch}/" /etc/maicore_install.conf +>>>>>>> Stashed changes + BRANCH="${new_branch}" + check_eula + systemctl restart ${SERVICE_NAME} + whiptail --msgbox "✅ 已切换到分支 ${new_branch} 并重启服务!" 10 60 +} + +<<<<<<< Updated upstream +# 更新配置文件 +update_config() { + cd "${INSTALL_DIR}/repo" || { + whiptail --msgbox "🚫 无法进入安装目录!" 10 60 + return 1 + } + if [[ -f config/bot_config.toml ]]; then + cp config/bot_config.toml config/bot_config.toml.bak + whiptail --msgbox "📁 原配置文件已备份为 bot_config.toml.bak" 10 60 + source "${INSTALL_DIR}/venv/bin/activate" + python3 config/auto_update.py + deactivate + whiptail --msgbox "🆕 已更新配置文件,请重启麦麦Bot!" 10 60 + return 0 + else + whiptail --msgbox "🚫 未找到配置文件 bot_config.toml\n 请先运行一次麦麦Bot" 10 60 + return 1 + fi +} + +check_eula() { + # 首先计算当前EULA的MD5值 + current_md5=$(md5sum "${INSTALL_DIR}/repo/EULA.md" | awk '{print $1}') + + # 首先计算当前隐私条款文件的哈希值 + current_md5_privacy=$(md5sum "${INSTALL_DIR}/repo/PRIVACY.md" | awk '{print $1}') +======= +check_eula() { + # 首先计算当前EULA的MD5值 + current_md5=$(md5sum "${INSTALL_DIR}/MaiBot/EULA.md" | awk '{print $1}') + + # 首先计算当前隐私条款文件的哈希值 + current_md5_privacy=$(md5sum "${INSTALL_DIR}/MaiBot/PRIVACY.md" | awk '{print $1}') +>>>>>>> Stashed changes + + # 如果当前的md5值为空,则直接返回 + if [[ -z $current_md5 || -z $current_md5_privacy ]]; then + whiptail --msgbox "🚫 未找到使用协议\n 请检查PRIVACY.md和EULA.md是否存在" 10 60 + fi + + # 检查eula.confirmed文件是否存在 +<<<<<<< Updated upstream + if [[ -f ${INSTALL_DIR}/repo/eula.confirmed ]]; then + # 如果存在则检查其中包含的md5与current_md5是否一致 + confirmed_md5=$(cat ${INSTALL_DIR}/repo/eula.confirmed) +======= + if [[ -f ${INSTALL_DIR}/MaiBot/eula.confirmed ]]; then + # 如果存在则检查其中包含的md5与current_md5是否一致 + confirmed_md5=$(cat ${INSTALL_DIR}/MaiBot/eula.confirmed) +>>>>>>> Stashed changes + else + confirmed_md5="" + fi + + # 检查privacy.confirmed文件是否存在 +<<<<<<< Updated upstream + if [[ -f ${INSTALL_DIR}/repo/privacy.confirmed ]]; then + # 如果存在则检查其中包含的md5与current_md5是否一致 + confirmed_md5_privacy=$(cat ${INSTALL_DIR}/repo/privacy.confirmed) +======= + if [[ -f ${INSTALL_DIR}/MaiBot/privacy.confirmed ]]; then + # 如果存在则检查其中包含的md5与current_md5是否一致 + confirmed_md5_privacy=$(cat ${INSTALL_DIR}/MaiBot/privacy.confirmed) +>>>>>>> Stashed changes + else + confirmed_md5_privacy="" + fi + + # 如果EULA或隐私条款有更新,提示用户重新确认 + if [[ $current_md5 != $confirmed_md5 || $current_md5_privacy != $confirmed_md5_privacy ]]; then +<<<<<<< Updated upstream + whiptail --title "📜 使用协议更新" --yesno "检测到麦麦Bot EULA或隐私条款已更新。\nhttps://github.com/SengokuCola/MaiMBot/blob/main/EULA.md\nhttps://github.com/SengokuCola/MaiMBot/blob/main/PRIVACY.md\n\n您是否同意上述协议? \n\n " 12 70 + if [[ $? -eq 0 ]]; then + echo -n $current_md5 > ${INSTALL_DIR}/repo/eula.confirmed + echo -n $current_md5_privacy > ${INSTALL_DIR}/repo/privacy.confirmed +======= + whiptail --title "📜 使用协议更新" --yesno "检测到MaiCore EULA或隐私条款已更新。\nhttps://github.com/MaiM-with-u/MaiBot/blob/refactor/EULA.md\nhttps://github.com/MaiM-with-u/MaiBot/blob/refactor/PRIVACY.md\n\n您是否同意上述协议? \n\n " 12 70 + if [[ $? -eq 0 ]]; then + echo -n $current_md5 > ${INSTALL_DIR}/MaiBot/eula.confirmed + echo -n $current_md5_privacy > ${INSTALL_DIR}/MaiBot/privacy.confirmed +>>>>>>> Stashed changes + else + exit 1 + fi + fi + +} + +# ----------- 主安装流程 ----------- +run_installation() { + # 1/6: 检测是否安装 whiptail + if ! command -v whiptail &>/dev/null; then + echo -e "${RED}[1/6] whiptail 未安装,正在安装...${RESET}" + + # 这里的多系统适配很神人,但是能用() + + apt update && apt install -y whiptail + + pacman -S --noconfirm libnewt + + yum install -y newt + fi + + # 协议确认 +<<<<<<< Updated upstream + if ! (whiptail --title "ℹ️ [1/6] 使用协议" --yes-button "我同意" --no-button "我拒绝" --yesno "使用麦麦Bot及此脚本前请先阅读EULA协议及隐私协议\nhttps://github.com/SengokuCola/MaiMBot/blob/main/EULA.md\nhttps://github.com/SengokuCola/MaiMBot/blob/main/PRIVACY.md\n\n您是否同意上述协议?" 12 70); then +======= + if ! (whiptail --title "ℹ️ [1/6] 使用协议" --yes-button "我同意" --no-button "我拒绝" --yesno "使用MaiCore及此脚本前请先阅读EULA协议及隐私协议\nhttps://github.com/MaiM-with-u/MaiBot/blob/refactor/EULA.md\nhttps://github.com/MaiM-with-u/MaiBot/blob/refactor/PRIVACY.md\n\n您是否同意上述协议?" 12 70); then +>>>>>>> Stashed changes + exit 1 + fi + + # 欢迎信息 +<<<<<<< Updated upstream + whiptail --title "[2/6] 欢迎使用麦麦Bot一键安装脚本 by Cookie987" --msgbox "检测到您未安装麦麦Bot,将自动进入安装流程,安装完成后再次运行此脚本即可进入管理菜单。\n\n项目处于活跃开发阶段,代码可能随时更改\n文档未完善,有问题可以提交 Issue 或者 Discussion\nQQ机器人存在被限制风险,请自行了解,谨慎使用\n由于持续迭代,可能存在一些已知或未知的bug\n由于开发中,可能消耗较多token\n\n本脚本可能更新不及时,如遇到bug请优先尝试手动部署以确定是否为脚本问题" 17 60 +======= + whiptail --title "[2/6] 欢迎使用MaiCore一键安装脚本 by Cookie987" --msgbox "检测到您未安装MaiCore,将自动进入安装流程,安装完成后再次运行此脚本即可进入管理菜单。\n\n项目处于活跃开发阶段,代码可能随时更改\n文档未完善,有问题可以提交 Issue 或者 Discussion\nQQ机器人存在被限制风险,请自行了解,谨慎使用\n由于持续迭代,可能存在一些已知或未知的bug\n由于开发中,可能消耗较多token\n\n本脚本可能更新不及时,如遇到bug请优先尝试手动部署以确定是否为脚本问题" 17 60 +>>>>>>> Stashed changes + + # 系统检查 + check_system() { + if [[ "$(id -u)" -ne 0 ]]; then + whiptail --title "🚫 权限不足" --msgbox "请使用 root 用户运行此脚本!\n执行方式: sudo bash $0" 10 60 + exit 1 + fi + + if [[ -f /etc/os-release ]]; then + source /etc/os-release + if [[ "$ID" == "debian" && "$VERSION_ID" == "12" ]]; then + return + elif [[ "$ID" == "ubuntu" && "$VERSION_ID" == "24.10" ]]; then + return + elif [[ "$ID" == "centos" && "$VERSION_ID" == "9" ]]; then + return + elif [[ "$ID" == "arch" ]]; then + whiptail --title "⚠️ 兼容性警告" --msgbox "NapCat无可用的 Arch Linux 官方安装方法,将无法自动安装NapCat。\n\n您可尝试在AUR中搜索相关包。" 10 60 + whiptail --title "⚠️ 兼容性警告" --msgbox "MongoDB无可用的 Arch Linux 官方安装方法,将无法自动安装MongoDB。\n\n您可尝试在AUR中搜索相关包。" 10 60 + return + else + whiptail --title "🚫 不支持的系统" --msgbox "此脚本仅支持 Arch/Debian 12 (Bookworm)/Ubuntu 24.10 (Oracular Oriole)/CentOS9!\n当前系统: $PRETTY_NAME\n安装已终止。" 10 60 + exit 1 + fi + else + whiptail --title "⚠️ 无法检测系统" --msgbox "无法识别系统版本,安装已终止。" 10 60 + exit 1 + fi + } + check_system + + # 设置包管理器 + case "$ID" in + debian|ubuntu) + PKG_MANAGER="apt" + ;; + centos) + PKG_MANAGER="yum" + ;; + arch) + # 添加arch包管理器 + PKG_MANAGER="pacman" + ;; + esac + + # 检查MongoDB + check_mongodb() { + if command -v mongod &>/dev/null; then + MONGO_INSTALLED=true + else + MONGO_INSTALLED=false + fi + } + check_mongodb + + # 检查NapCat + check_napcat() { + if command -v napcat &>/dev/null; then + NAPCAT_INSTALLED=true + else + NAPCAT_INSTALLED=false + fi + } + check_napcat + + # 安装必要软件包 + install_packages() { + missing_packages=() + # 检查 common 及当前系统专属依赖 + for package in ${REQUIRED_PACKAGES["common"]} ${REQUIRED_PACKAGES["$ID"]}; do + case "$PKG_MANAGER" in + apt) + dpkg -s "$package" &>/dev/null || missing_packages+=("$package") + ;; + yum) + rpm -q "$package" &>/dev/null || missing_packages+=("$package") + ;; + pacman) + pacman -Qi "$package" &>/dev/null || missing_packages+=("$package") + ;; + esac + done + + if [[ ${#missing_packages[@]} -gt 0 ]]; then + whiptail --title "📦 [3/6] 依赖检查" --yesno "以下软件包缺失:\n${missing_packages[*]}\n\n是否自动安装?" 10 60 + if [[ $? -eq 0 ]]; then + IS_INSTALL_DEPENDENCIES=true + else + whiptail --title "⚠️ 注意" --yesno "未安装某些依赖,可能影响运行!\n是否继续?" 10 60 || exit 1 + fi + fi + } + install_packages + + # 安装MongoDB + install_mongodb() { + [[ $MONGO_INSTALLED == true ]] && return + whiptail --title "📦 [3/6] 软件包检查" --yesno "检测到未安装MongoDB,是否安装?\n如果您想使用远程数据库,请跳过此步。" 10 60 && { + IS_INSTALL_MONGODB=true + } + } + + # 仅在非Arch系统上安装MongoDB + [[ "$ID" != "arch" ]] && install_mongodb + + + # 安装NapCat + install_napcat() { + [[ $NAPCAT_INSTALLED == true ]] && return + whiptail --title "📦 [3/6] 软件包检查" --yesno "检测到未安装NapCat,是否安装?\n如果您想使用远程NapCat,请跳过此步。" 10 60 && { + IS_INSTALL_NAPCAT=true + } + } + + # 仅在非Arch系统上安装NapCat + [[ "$ID" != "arch" ]] && install_napcat + + # Python版本检查 + check_python() { + PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') + if ! python3 -c "import sys; exit(0) if sys.version_info >= (3,9) else exit(1)"; then + whiptail --title "⚠️ [4/6] Python 版本过低" --msgbox "检测到 Python 版本为 $PYTHON_VERSION,需要 3.9 或以上!\n请升级 Python 后重新运行本脚本。" 10 60 + exit 1 + fi + } + + # 如果没安装python则不检查python版本 + if command -v python3 &>/dev/null; then + check_python + fi + + + # 选择分支 + choose_branch() { +<<<<<<< Updated upstream + BRANCH=$(whiptail --title "🔀 [5/6] 选择麦麦Bot分支" --menu "请选择要安装的麦麦Bot分支:" 15 60 2 \ + "main" "稳定版本(推荐,供下载使用)" \ + "main-fix" "生产环境紧急修复" 3>&1 1>&2 2>&3) + [[ -z "$BRANCH" ]] && BRANCH="main" +======= + BRANCH=refactor +>>>>>>> Stashed changes + } + choose_branch + + # 选择安装路径 + choose_install_dir() { +<<<<<<< Updated upstream + INSTALL_DIR=$(whiptail --title "📂 [6/6] 选择安装路径" --inputbox "请输入麦麦Bot的安装目录:" 10 60 "$DEFAULT_INSTALL_DIR" 3>&1 1>&2 2>&3) +======= + INSTALL_DIR=$(whiptail --title "📂 [6/6] 选择安装路径" --inputbox "请输入MaiCore的安装目录:" 10 60 "$DEFAULT_INSTALL_DIR" 3>&1 1>&2 2>&3) +>>>>>>> Stashed changes + [[ -z "$INSTALL_DIR" ]] && { + whiptail --title "⚠️ 取消输入" --yesno "未输入安装路径,是否退出安装?" 10 60 && exit 1 + INSTALL_DIR="$DEFAULT_INSTALL_DIR" + } + } + choose_install_dir + + # 确认安装 + confirm_install() { + local confirm_msg="请确认以下信息:\n\n" +<<<<<<< Updated upstream + confirm_msg+="📂 安装麦麦Bot到: $INSTALL_DIR\n" +======= + confirm_msg+="📂 安装MaiCore到: $INSTALL_DIR\n" +>>>>>>> Stashed changes + confirm_msg+="🔀 分支: $BRANCH\n" + [[ $IS_INSTALL_DEPENDENCIES == true ]] && confirm_msg+="📦 安装依赖:${missing_packages[@]}\n" + [[ $IS_INSTALL_MONGODB == true || $IS_INSTALL_NAPCAT == true ]] && confirm_msg+="📦 安装额外组件:\n" + + [[ $IS_INSTALL_MONGODB == true ]] && confirm_msg+=" - MongoDB\n" + [[ $IS_INSTALL_NAPCAT == true ]] && confirm_msg+=" - NapCat\n" + confirm_msg+="\n注意:本脚本默认使用ghfast.top为GitHub进行加速,如不想使用请手动修改脚本开头的GITHUB_REPO变量。" + + whiptail --title "🔧 安装确认" --yesno "$confirm_msg" 20 60 || exit 1 + } + confirm_install + + # 开始安装 + echo -e "${GREEN}安装${missing_packages[@]}...${RESET}" + + if [[ $IS_INSTALL_DEPENDENCIES == true ]]; then + case "$PKG_MANAGER" in + apt) + apt update && apt install -y "${missing_packages[@]}" + ;; + yum) + yum install -y "${missing_packages[@]}" --nobest + ;; + pacman) + pacman -S --noconfirm "${missing_packages[@]}" + ;; + esac + fi + + if [[ $IS_INSTALL_MONGODB == true ]]; then + echo -e "${GREEN}安装 MongoDB...${RESET}" + case "$ID" in + debian) + curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor + echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] http://repo.mongodb.org/apt/debian bookworm/mongodb-org/8.0 main" | tee /etc/apt/sources.list.d/mongodb-org-8.0.list + apt update + apt install -y mongodb-org + systemctl enable --now mongod + ;; + ubuntu) + curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor + echo "deb [ signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] http://repo.mongodb.org/apt/debian bookworm/mongodb-org/8.0 main" | tee /etc/apt/sources.list.d/mongodb-org-8.0.list + apt update + apt install -y mongodb-org + systemctl enable --now mongod + ;; + centos) + cat > /etc/yum.repos.d/mongodb-org-8.0.repo < pyproject.toml < README.md + mkdir src + cp -r ../../nonebot-plugin-maibot-adapters/nonebot_plugin_maibot_adapters src/plugins + cd .. + cd .. + +>>>>>>> Stashed changes + + echo -e "${GREEN}同意协议...${RESET}" + + # 首先计算当前EULA的MD5值 +<<<<<<< Updated upstream + current_md5=$(md5sum "repo/EULA.md" | awk '{print $1}') + + # 首先计算当前隐私条款文件的哈希值 + current_md5_privacy=$(md5sum "repo/PRIVACY.md" | awk '{print $1}') + + echo -n $current_md5 > repo/eula.confirmed + echo -n $current_md5_privacy > repo/privacy.confirmed +======= + current_md5=$(md5sum "MaiBot/EULA.md" | awk '{print $1}') + + # 首先计算当前隐私条款文件的哈希值 + current_md5_privacy=$(md5sum "MaiBot/PRIVACY.md" | awk '{print $1}') + + echo -n $current_md5 > MaiBot/eula.confirmed + echo -n $current_md5_privacy > MaiBot/privacy.confirmed +>>>>>>> Stashed changes + + echo -e "${GREEN}创建系统服务...${RESET}" + cat > /etc/systemd/system/${SERVICE_NAME}.service <>>>>>> Stashed changes +ExecStart=$INSTALL_DIR/venv/bin/python3 bot.py +Restart=always +RestartSec=10s + +[Install] +WantedBy=multi-user.target +EOF + + cat > /etc/systemd/system/${SERVICE_NAME_WEB}.service <>>>>>> Stashed changes +After=network.target mongod.service ${SERVICE_NAME}.service + +[Service] +Type=simple +<<<<<<< Updated upstream +WorkingDirectory=${INSTALL_DIR}/repo +======= +WorkingDirectory=${INSTALL_DIR}/MaiBot +>>>>>>> Stashed changes +ExecStart=$INSTALL_DIR/venv/bin/python3 webui.py +Restart=always +RestartSec=10s + +[Install] +WantedBy=multi-user.target +EOF + +<<<<<<< Updated upstream +======= + cat > /etc/systemd/system/${SERVICE_NAME_NBADAPTER}.service <>>>>>> Stashed changes + systemctl daemon-reload + systemctl enable ${SERVICE_NAME} + + # 保存安装信息 +<<<<<<< Updated upstream + echo "INSTALLER_VERSION=${INSTALLER_VERSION}" > /etc/maimbot_install.conf + echo "INSTALL_DIR=${INSTALL_DIR}" >> /etc/maimbot_install.conf + echo "BRANCH=${BRANCH}" >> /etc/maimbot_install.conf + + whiptail --title "🎉 安装完成" --msgbox "麦麦Bot安装完成!\n已创建系统服务:${SERVICE_NAME},${SERVICE_NAME_WEB}\n\n使用以下命令管理服务:\n启动服务:systemctl start ${SERVICE_NAME}\n查看状态:systemctl status ${SERVICE_NAME}" 14 60 +======= + echo "INSTALLER_VERSION=${INSTALLER_VERSION}" > /etc/maicore_install.conf + echo "INSTALL_DIR=${INSTALL_DIR}" >> /etc/maicore_install.conf + echo "BRANCH=${BRANCH}" >> /etc/maicore_install.conf + + whiptail --title "🎉 安装完成" --msgbox "MaiCore安装完成!\n已创建系统服务:${SERVICE_NAME},${SERVICE_NAME_WEB}\n\n使用以下命令管理服务:\n启动服务:systemctl start ${SERVICE_NAME}\n查看状态:systemctl status ${SERVICE_NAME}" 14 60 +>>>>>>> Stashed changes +} + +# ----------- 主执行流程 ----------- +# 检查root权限 +[[ $(id -u) -ne 0 ]] && { + echo -e "${RED}请使用root用户运行此脚本!${RESET}" + exit 1 +} + +# 如果已安装显示菜单,并检查协议是否更新 +if check_installed; then + load_install_info + check_eula + show_menu +else + run_installation + # 安装完成后询问是否启动 +<<<<<<< Updated upstream + if whiptail --title "安装完成" --yesno "是否立即启动麦麦Bot服务?" 10 60; then + systemctl start ${SERVICE_NAME} + whiptail --msgbox "✅ 服务已启动!\n使用 systemctl status ${SERVICE_NAME} 查看状态" 10 60 + fi +fi +======= + if whiptail --title "安装完成" --yesno "是否立即启动MaiCore服务?" 10 60; then + systemctl start ${SERVICE_NAME} + whiptail --msgbox "✅ 服务已启动!\n使用 systemctl status ${SERVICE_NAME} 查看状态" 10 60 + fi +fi +>>>>>>> Stashed changes From 8afc913994f8a732116ef37ccf9fbc83b7da79ba Mon Sep 17 00:00:00 2001 From: Cookie987 Date: Wed, 2 Apr 2025 14:41:11 +0800 Subject: [PATCH 04/16] Update run.sh --- run.sh | 209 --------------------------------------------------------- 1 file changed, 209 deletions(-) diff --git a/run.sh b/run.sh index 6e95ab9e..2f87017b 100644 --- a/run.sh +++ b/run.sh @@ -1,16 +1,5 @@ #!/bin/bash -<<<<<<< Updated upstream -# 麦麦Bot一键安装脚本 by Cookie_987 -# 适用于Arch/Ubuntu 24.10/Debian 12/CentOS 9 -# 请小心使用任何一键脚本! - -INSTALLER_VERSION="0.0.3" -LANG=C.UTF-8 - -# 如无法访问GitHub请修改此处镜像地址 -GITHUB_REPO="https://ghfast.top/https://github.com/SengokuCola/MaiMBot.git" -======= # MaiCore & Nonebot adapter一键安装脚本 by Cookie_987 # 适用于Arch/Ubuntu 24.10/Debian 12/CentOS 9 # 请小心使用任何一键脚本! @@ -20,7 +9,6 @@ LANG=C.UTF-8 # 如无法访问GitHub请修改此处镜像地址 GITHUB_REPO="https://github.com/MaiM-with-u/MaiBot.git" ->>>>>>> Stashed changes # 颜色输出 GREEN="\e[32m" @@ -41,14 +29,9 @@ declare -A REQUIRED_PACKAGES=( DEFAULT_INSTALL_DIR="/opt/maimbot" # 服务名称 -<<<<<<< Updated upstream -SERVICE_NAME="maimbot-daemon" -SERVICE_NAME_WEB="maimbot-web" -======= SERVICE_NAME="maicore" SERVICE_NAME_WEB="maicore-web" SERVICE_NAME_NBADAPTER="maicore-nonebot-adapter" ->>>>>>> Stashed changes IS_INSTALL_MONGODB=false IS_INSTALL_NAPCAT=false @@ -61,38 +44,17 @@ check_installed() { # 加载安装信息 load_install_info() { -<<<<<<< Updated upstream - if [[ -f /etc/maimbot_install.conf ]]; then - source /etc/maimbot_install.conf - else - INSTALL_DIR="$DEFAULT_INSTALL_DIR" - BRANCH="main" -======= if [[ -f /etc/maicore_install.conf ]]; then source /etc/maicore_install.conf else INSTALL_DIR="$DEFAULT_INSTALL_DIR" BRANCH="refactor" ->>>>>>> Stashed changes fi } # 显示管理菜单 show_menu() { while true; do -<<<<<<< Updated upstream - choice=$(whiptail --title "麦麦Bot管理菜单" --menu "请选择要执行的操作:" 15 60 7 \ - "1" "启动麦麦Bot" \ - "2" "停止麦麦Bot" \ - "3" "重启麦麦Bot" \ - "4" "启动WebUI" \ - "5" "停止WebUI" \ - "6" "重启WebUI" \ - "7" "更新麦麦Bot及其依赖" \ - "8" "切换分支" \ - "9" "更新配置文件" \ - "10" "退出" 3>&1 1>&2 2>&3) -======= choice=$(whiptail --title "MaiCore管理菜单" --menu "请选择要执行的操作:" 15 60 7 \ "1" "启动MaiCore" \ "2" "停止MaiCore" \ @@ -103,36 +65,12 @@ show_menu() { "7" "更新MaiCore及其依赖" \ "8" "切换分支" \ "9" "退出" 3>&1 1>&2 2>&3) ->>>>>>> Stashed changes [[ $? -ne 0 ]] && exit 0 case "$choice" in 1) systemctl start ${SERVICE_NAME} -<<<<<<< Updated upstream - whiptail --msgbox "✅麦麦Bot已启动" 10 60 - ;; - 2) - systemctl stop ${SERVICE_NAME} - whiptail --msgbox "🛑麦麦Bot已停止" 10 60 - ;; - 3) - systemctl restart ${SERVICE_NAME} - whiptail --msgbox "🔄麦麦Bot已重启" 10 60 - ;; - 4) - systemctl start ${SERVICE_NAME_WEB} - whiptail --msgbox "✅WebUI已启动" 10 60 - ;; - 5) - systemctl stop ${SERVICE_NAME_WEB} - whiptail --msgbox "🛑WebUI已停止" 10 60 - ;; - 6) - systemctl restart ${SERVICE_NAME_WEB} - whiptail --msgbox "🔄WebUI已重启" 10 60 -======= whiptail --msgbox "✅MaiCore已启动" 10 60 ;; 2) @@ -154,7 +92,6 @@ show_menu() { 6) systemctl restart ${SERVICE_NAME_NBADAPTER} whiptail --msgbox "🔄Nonebot adapter已重启" 10 60 ->>>>>>> Stashed changes ;; 7) update_dependencies @@ -163,12 +100,6 @@ show_menu() { switch_branch ;; 9) -<<<<<<< Updated upstream - update_config - ;; - 10) -======= ->>>>>>> Stashed changes exit 0 ;; *) @@ -180,11 +111,7 @@ show_menu() { # 更新依赖 update_dependencies() { -<<<<<<< Updated upstream - cd "${INSTALL_DIR}/repo" || { -======= cd "${INSTALL_DIR}/MaiBot" || { ->>>>>>> Stashed changes whiptail --msgbox "🚫 无法进入安装目录!" 10 60 return 1 } @@ -211,11 +138,7 @@ switch_branch() { return 1 } -<<<<<<< Updated upstream - cd "${INSTALL_DIR}/repo" || { -======= cd "${INSTALL_DIR}/MaiBot" || { ->>>>>>> Stashed changes whiptail --msgbox "🚫 无法进入安装目录!" 10 60 return 1 } @@ -239,52 +162,19 @@ switch_branch() { pip install -r requirements.txt deactivate -<<<<<<< Updated upstream - sed -i "s/^BRANCH=.*/BRANCH=${new_branch}/" /etc/maimbot_install.conf -======= sed -i "s/^BRANCH=.*/BRANCH=${new_branch}/" /etc/maicore_install.conf ->>>>>>> Stashed changes BRANCH="${new_branch}" check_eula systemctl restart ${SERVICE_NAME} whiptail --msgbox "✅ 已切换到分支 ${new_branch} 并重启服务!" 10 60 } -<<<<<<< Updated upstream -# 更新配置文件 -update_config() { - cd "${INSTALL_DIR}/repo" || { - whiptail --msgbox "🚫 无法进入安装目录!" 10 60 - return 1 - } - if [[ -f config/bot_config.toml ]]; then - cp config/bot_config.toml config/bot_config.toml.bak - whiptail --msgbox "📁 原配置文件已备份为 bot_config.toml.bak" 10 60 - source "${INSTALL_DIR}/venv/bin/activate" - python3 config/auto_update.py - deactivate - whiptail --msgbox "🆕 已更新配置文件,请重启麦麦Bot!" 10 60 - return 0 - else - whiptail --msgbox "🚫 未找到配置文件 bot_config.toml\n 请先运行一次麦麦Bot" 10 60 - return 1 - fi -} - -check_eula() { - # 首先计算当前EULA的MD5值 - current_md5=$(md5sum "${INSTALL_DIR}/repo/EULA.md" | awk '{print $1}') - - # 首先计算当前隐私条款文件的哈希值 - current_md5_privacy=$(md5sum "${INSTALL_DIR}/repo/PRIVACY.md" | awk '{print $1}') -======= check_eula() { # 首先计算当前EULA的MD5值 current_md5=$(md5sum "${INSTALL_DIR}/MaiBot/EULA.md" | awk '{print $1}') # 首先计算当前隐私条款文件的哈希值 current_md5_privacy=$(md5sum "${INSTALL_DIR}/MaiBot/PRIVACY.md" | awk '{print $1}') ->>>>>>> Stashed changes # 如果当前的md5值为空,则直接返回 if [[ -z $current_md5 || -z $current_md5_privacy ]]; then @@ -292,46 +182,27 @@ check_eula() { fi # 检查eula.confirmed文件是否存在 -<<<<<<< Updated upstream - if [[ -f ${INSTALL_DIR}/repo/eula.confirmed ]]; then - # 如果存在则检查其中包含的md5与current_md5是否一致 - confirmed_md5=$(cat ${INSTALL_DIR}/repo/eula.confirmed) -======= if [[ -f ${INSTALL_DIR}/MaiBot/eula.confirmed ]]; then # 如果存在则检查其中包含的md5与current_md5是否一致 confirmed_md5=$(cat ${INSTALL_DIR}/MaiBot/eula.confirmed) ->>>>>>> Stashed changes else confirmed_md5="" fi # 检查privacy.confirmed文件是否存在 -<<<<<<< Updated upstream - if [[ -f ${INSTALL_DIR}/repo/privacy.confirmed ]]; then - # 如果存在则检查其中包含的md5与current_md5是否一致 - confirmed_md5_privacy=$(cat ${INSTALL_DIR}/repo/privacy.confirmed) -======= if [[ -f ${INSTALL_DIR}/MaiBot/privacy.confirmed ]]; then # 如果存在则检查其中包含的md5与current_md5是否一致 confirmed_md5_privacy=$(cat ${INSTALL_DIR}/MaiBot/privacy.confirmed) ->>>>>>> Stashed changes else confirmed_md5_privacy="" fi # 如果EULA或隐私条款有更新,提示用户重新确认 if [[ $current_md5 != $confirmed_md5 || $current_md5_privacy != $confirmed_md5_privacy ]]; then -<<<<<<< Updated upstream - whiptail --title "📜 使用协议更新" --yesno "检测到麦麦Bot EULA或隐私条款已更新。\nhttps://github.com/SengokuCola/MaiMBot/blob/main/EULA.md\nhttps://github.com/SengokuCola/MaiMBot/blob/main/PRIVACY.md\n\n您是否同意上述协议? \n\n " 12 70 - if [[ $? -eq 0 ]]; then - echo -n $current_md5 > ${INSTALL_DIR}/repo/eula.confirmed - echo -n $current_md5_privacy > ${INSTALL_DIR}/repo/privacy.confirmed -======= whiptail --title "📜 使用协议更新" --yesno "检测到MaiCore EULA或隐私条款已更新。\nhttps://github.com/MaiM-with-u/MaiBot/blob/refactor/EULA.md\nhttps://github.com/MaiM-with-u/MaiBot/blob/refactor/PRIVACY.md\n\n您是否同意上述协议? \n\n " 12 70 if [[ $? -eq 0 ]]; then echo -n $current_md5 > ${INSTALL_DIR}/MaiBot/eula.confirmed echo -n $current_md5_privacy > ${INSTALL_DIR}/MaiBot/privacy.confirmed ->>>>>>> Stashed changes else exit 1 fi @@ -355,20 +226,12 @@ run_installation() { fi # 协议确认 -<<<<<<< Updated upstream - if ! (whiptail --title "ℹ️ [1/6] 使用协议" --yes-button "我同意" --no-button "我拒绝" --yesno "使用麦麦Bot及此脚本前请先阅读EULA协议及隐私协议\nhttps://github.com/SengokuCola/MaiMBot/blob/main/EULA.md\nhttps://github.com/SengokuCola/MaiMBot/blob/main/PRIVACY.md\n\n您是否同意上述协议?" 12 70); then -======= if ! (whiptail --title "ℹ️ [1/6] 使用协议" --yes-button "我同意" --no-button "我拒绝" --yesno "使用MaiCore及此脚本前请先阅读EULA协议及隐私协议\nhttps://github.com/MaiM-with-u/MaiBot/blob/refactor/EULA.md\nhttps://github.com/MaiM-with-u/MaiBot/blob/refactor/PRIVACY.md\n\n您是否同意上述协议?" 12 70); then ->>>>>>> Stashed changes exit 1 fi # 欢迎信息 -<<<<<<< Updated upstream - whiptail --title "[2/6] 欢迎使用麦麦Bot一键安装脚本 by Cookie987" --msgbox "检测到您未安装麦麦Bot,将自动进入安装流程,安装完成后再次运行此脚本即可进入管理菜单。\n\n项目处于活跃开发阶段,代码可能随时更改\n文档未完善,有问题可以提交 Issue 或者 Discussion\nQQ机器人存在被限制风险,请自行了解,谨慎使用\n由于持续迭代,可能存在一些已知或未知的bug\n由于开发中,可能消耗较多token\n\n本脚本可能更新不及时,如遇到bug请优先尝试手动部署以确定是否为脚本问题" 17 60 -======= whiptail --title "[2/6] 欢迎使用MaiCore一键安装脚本 by Cookie987" --msgbox "检测到您未安装MaiCore,将自动进入安装流程,安装完成后再次运行此脚本即可进入管理菜单。\n\n项目处于活跃开发阶段,代码可能随时更改\n文档未完善,有问题可以提交 Issue 或者 Discussion\nQQ机器人存在被限制风险,请自行了解,谨慎使用\n由于持续迭代,可能存在一些已知或未知的bug\n由于开发中,可能消耗较多token\n\n本脚本可能更新不及时,如遇到bug请优先尝试手动部署以确定是否为脚本问题" 17 60 ->>>>>>> Stashed changes # 系统检查 check_system() { @@ -503,24 +366,13 @@ run_installation() { # 选择分支 choose_branch() { -<<<<<<< Updated upstream - BRANCH=$(whiptail --title "🔀 [5/6] 选择麦麦Bot分支" --menu "请选择要安装的麦麦Bot分支:" 15 60 2 \ - "main" "稳定版本(推荐,供下载使用)" \ - "main-fix" "生产环境紧急修复" 3>&1 1>&2 2>&3) - [[ -z "$BRANCH" ]] && BRANCH="main" -======= BRANCH=refactor ->>>>>>> Stashed changes } choose_branch # 选择安装路径 choose_install_dir() { -<<<<<<< Updated upstream - INSTALL_DIR=$(whiptail --title "📂 [6/6] 选择安装路径" --inputbox "请输入麦麦Bot的安装目录:" 10 60 "$DEFAULT_INSTALL_DIR" 3>&1 1>&2 2>&3) -======= INSTALL_DIR=$(whiptail --title "📂 [6/6] 选择安装路径" --inputbox "请输入MaiCore的安装目录:" 10 60 "$DEFAULT_INSTALL_DIR" 3>&1 1>&2 2>&3) ->>>>>>> Stashed changes [[ -z "$INSTALL_DIR" ]] && { whiptail --title "⚠️ 取消输入" --yesno "未输入安装路径,是否退出安装?" 10 60 && exit 1 INSTALL_DIR="$DEFAULT_INSTALL_DIR" @@ -531,11 +383,7 @@ run_installation() { # 确认安装 confirm_install() { local confirm_msg="请确认以下信息:\n\n" -<<<<<<< Updated upstream - confirm_msg+="📂 安装麦麦Bot到: $INSTALL_DIR\n" -======= confirm_msg+="📂 安装MaiCore到: $INSTALL_DIR\n" ->>>>>>> Stashed changes confirm_msg+="🔀 分支: $BRANCH\n" [[ $IS_INSTALL_DEPENDENCIES == true ]] && confirm_msg+="📦 安装依赖:${missing_packages[@]}\n" [[ $IS_INSTALL_MONGODB == true || $IS_INSTALL_NAPCAT == true ]] && confirm_msg+="📦 安装额外组件:\n" @@ -611,16 +459,6 @@ EOF python3 -m venv venv source venv/bin/activate -<<<<<<< Updated upstream - echo -e "${GREEN}克隆仓库...${RESET}" - git clone -b "$BRANCH" "$GITHUB_REPO" repo || { - echo -e "${RED}克隆仓库失败!${RESET}" - exit 1 - } - - echo -e "${GREEN}安装Python依赖...${RESET}" - pip install -r repo/requirements.txt -======= echo -e "${GREEN}克隆MaiCore仓库...${RESET}" git clone -b "$BRANCH" "$GITHUB_REPO" MaiBot || { echo -e "${RED}克隆MaiCore仓库失败!${RESET}" @@ -675,20 +513,10 @@ EOF cd .. cd .. ->>>>>>> Stashed changes echo -e "${GREEN}同意协议...${RESET}" # 首先计算当前EULA的MD5值 -<<<<<<< Updated upstream - current_md5=$(md5sum "repo/EULA.md" | awk '{print $1}') - - # 首先计算当前隐私条款文件的哈希值 - current_md5_privacy=$(md5sum "repo/PRIVACY.md" | awk '{print $1}') - - echo -n $current_md5 > repo/eula.confirmed - echo -n $current_md5_privacy > repo/privacy.confirmed -======= current_md5=$(md5sum "MaiBot/EULA.md" | awk '{print $1}') # 首先计算当前隐私条款文件的哈希值 @@ -696,26 +524,16 @@ EOF echo -n $current_md5 > MaiBot/eula.confirmed echo -n $current_md5_privacy > MaiBot/privacy.confirmed ->>>>>>> Stashed changes echo -e "${GREEN}创建系统服务...${RESET}" cat > /etc/systemd/system/${SERVICE_NAME}.service <>>>>>> Stashed changes ExecStart=$INSTALL_DIR/venv/bin/python3 bot.py Restart=always RestartSec=10s @@ -726,20 +544,12 @@ EOF cat > /etc/systemd/system/${SERVICE_NAME_WEB}.service <>>>>>> Stashed changes After=network.target mongod.service ${SERVICE_NAME}.service [Service] Type=simple -<<<<<<< Updated upstream -WorkingDirectory=${INSTALL_DIR}/repo -======= WorkingDirectory=${INSTALL_DIR}/MaiBot ->>>>>>> Stashed changes ExecStart=$INSTALL_DIR/venv/bin/python3 webui.py Restart=always RestartSec=10s @@ -748,8 +558,6 @@ RestartSec=10s WantedBy=multi-user.target EOF -<<<<<<< Updated upstream -======= cat > /etc/systemd/system/${SERVICE_NAME_NBADAPTER}.service <>>>>>> Stashed changes systemctl daemon-reload systemctl enable ${SERVICE_NAME} # 保存安装信息 -<<<<<<< Updated upstream - echo "INSTALLER_VERSION=${INSTALLER_VERSION}" > /etc/maimbot_install.conf - echo "INSTALL_DIR=${INSTALL_DIR}" >> /etc/maimbot_install.conf - echo "BRANCH=${BRANCH}" >> /etc/maimbot_install.conf - - whiptail --title "🎉 安装完成" --msgbox "麦麦Bot安装完成!\n已创建系统服务:${SERVICE_NAME},${SERVICE_NAME_WEB}\n\n使用以下命令管理服务:\n启动服务:systemctl start ${SERVICE_NAME}\n查看状态:systemctl status ${SERVICE_NAME}" 14 60 -======= echo "INSTALLER_VERSION=${INSTALLER_VERSION}" > /etc/maicore_install.conf echo "INSTALL_DIR=${INSTALL_DIR}" >> /etc/maicore_install.conf echo "BRANCH=${BRANCH}" >> /etc/maicore_install.conf whiptail --title "🎉 安装完成" --msgbox "MaiCore安装完成!\n已创建系统服务:${SERVICE_NAME},${SERVICE_NAME_WEB}\n\n使用以下命令管理服务:\n启动服务:systemctl start ${SERVICE_NAME}\n查看状态:systemctl status ${SERVICE_NAME}" 14 60 ->>>>>>> Stashed changes } # ----------- 主执行流程 ----------- @@ -801,16 +600,8 @@ if check_installed; then else run_installation # 安装完成后询问是否启动 -<<<<<<< Updated upstream - if whiptail --title "安装完成" --yesno "是否立即启动麦麦Bot服务?" 10 60; then - systemctl start ${SERVICE_NAME} - whiptail --msgbox "✅ 服务已启动!\n使用 systemctl status ${SERVICE_NAME} 查看状态" 10 60 - fi -fi -======= if whiptail --title "安装完成" --yesno "是否立即启动MaiCore服务?" 10 60; then systemctl start ${SERVICE_NAME} whiptail --msgbox "✅ 服务已启动!\n使用 systemctl status ${SERVICE_NAME} 查看状态" 10 60 fi fi ->>>>>>> Stashed changes From 1934aa30f28ca38390e4032f8ac3d8ddb9fe4fff Mon Sep 17 00:00:00 2001 From: infinitycat Date: Wed, 2 Apr 2025 15:24:12 +0800 Subject: [PATCH 05/16] =?UTF-8?q?build:=E4=B8=BA=20Docker=20=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E6=B7=BB=E5=8A=A0=20entrypoint=20=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 entrypoint.sh脚本,用于在容器启动时执行初始化操作 - 修改 Dockerfile,使用 entrypoint.sh 作为入口点 - 脚本功能包括: - 创建配置目录 - 复制 bot配置文件 - 复制环境配置文件 --- Dockerfile | 6 +++++- entrypoint.sh | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 entrypoint.sh diff --git a/Dockerfile b/Dockerfile index 6c6041ff..3addda1c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,4 +17,8 @@ RUN pip install --upgrade -r requirements.txt COPY . . EXPOSE 8000 -ENTRYPOINT [ "python","bot.py" ] \ No newline at end of file + +RUN chmod +x /MaiMBot/entrypoint.sh +ENTRYPOINT ["/MaiMBot/entrypoint.sh"] + +CMD [ "python","bot.py" ] \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 00000000..f8b5d778 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,55 @@ +#!/bin/sh +set -e # 遇到任何错误立即退出 + +# 定义常量 +TEMPLATE_DIR="./template" +CONFIG_DIR="./config" +TARGET_ENV_FILE="./.env" + +# 步骤 1: 创建 config 目录 +if [ ! -d "$CONFIG_DIR" ]; then + echo "🛠️ 创建配置目录: $CONFIG_DIR" + mkdir -p "$CONFIG_DIR" + chmod 755 "$CONFIG_DIR" # 设置目录权限(按需修改) +else + echo "ℹ️ 配置目录已存在,跳过创建: $CONFIG_DIR" +fi + +# 步骤 2: 复制 bot 配置文件 +BOT_TEMPLATE="$TEMPLATE_DIR/bot_config_template.toml" +BOT_CONFIG="$CONFIG_DIR/bot_config.toml" + +if [ -f "$BOT_TEMPLATE" ]; then + if [ ! -f "$BOT_CONFIG" ]; then + echo "📄 生成 Bot 配置文件: $BOT_CONFIG" + cp "$BOT_TEMPLATE" "$BOT_CONFIG" + chmod 644 "$BOT_CONFIG" # 设置文件权限(按需修改) + else + echo "ℹ️ Bot 配置文件已存在,跳过生成: $BOT_CONFIG" + fi +else + echo "❌ 错误:模板文件不存在: $BOT_TEMPLATE" >&2 + exit 1 +fi + +# 步骤 3: 复制环境文件 +ENV_TEMPLATE="$TEMPLATE_DIR/template.env" +ENV_TARGET="$TARGET_ENV_FILE" + +if [ -f "$ENV_TEMPLATE" ]; then + if [ ! -f "$ENV_TARGET" ]; then + echo "🔧 生成环境配置文件: $ENV_TARGET" + cp "$ENV_TEMPLATE" "$ENV_TARGET" + chmod 600 "$ENV_TARGET" # 敏感文件建议更严格权限 + else + echo "ℹ️ 环境文件已存在,跳过生成: $ENV_TARGET" + fi +else + echo "❌ 错误:模板文件不存在: $ENV_TEMPLATE" >&2 + exit 1 +fi + +echo "✅ 所有初始化完成!" + +# 执行 Docker CMD 命令 +exec "$@" \ No newline at end of file From 442b2065603bdc3e622cc41cc49a5ec038945863 Mon Sep 17 00:00:00 2001 From: infinitycat Date: Wed, 2 Apr 2025 16:53:43 +0800 Subject: [PATCH 06/16] =?UTF-8?q?=E5=BC=83=E7=94=A8entrypoint.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 5 +---- entrypoint.sh | 55 --------------------------------------------------- 2 files changed, 1 insertion(+), 59 deletions(-) delete mode 100644 entrypoint.sh diff --git a/Dockerfile b/Dockerfile index 3addda1c..fe96ac03 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,4 @@ COPY . . EXPOSE 8000 -RUN chmod +x /MaiMBot/entrypoint.sh -ENTRYPOINT ["/MaiMBot/entrypoint.sh"] - -CMD [ "python","bot.py" ] \ No newline at end of file +ENTRYPOINT [ "python","bot.py" ] \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh deleted file mode 100644 index f8b5d778..00000000 --- a/entrypoint.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh -set -e # 遇到任何错误立即退出 - -# 定义常量 -TEMPLATE_DIR="./template" -CONFIG_DIR="./config" -TARGET_ENV_FILE="./.env" - -# 步骤 1: 创建 config 目录 -if [ ! -d "$CONFIG_DIR" ]; then - echo "🛠️ 创建配置目录: $CONFIG_DIR" - mkdir -p "$CONFIG_DIR" - chmod 755 "$CONFIG_DIR" # 设置目录权限(按需修改) -else - echo "ℹ️ 配置目录已存在,跳过创建: $CONFIG_DIR" -fi - -# 步骤 2: 复制 bot 配置文件 -BOT_TEMPLATE="$TEMPLATE_DIR/bot_config_template.toml" -BOT_CONFIG="$CONFIG_DIR/bot_config.toml" - -if [ -f "$BOT_TEMPLATE" ]; then - if [ ! -f "$BOT_CONFIG" ]; then - echo "📄 生成 Bot 配置文件: $BOT_CONFIG" - cp "$BOT_TEMPLATE" "$BOT_CONFIG" - chmod 644 "$BOT_CONFIG" # 设置文件权限(按需修改) - else - echo "ℹ️ Bot 配置文件已存在,跳过生成: $BOT_CONFIG" - fi -else - echo "❌ 错误:模板文件不存在: $BOT_TEMPLATE" >&2 - exit 1 -fi - -# 步骤 3: 复制环境文件 -ENV_TEMPLATE="$TEMPLATE_DIR/template.env" -ENV_TARGET="$TARGET_ENV_FILE" - -if [ -f "$ENV_TEMPLATE" ]; then - if [ ! -f "$ENV_TARGET" ]; then - echo "🔧 生成环境配置文件: $ENV_TARGET" - cp "$ENV_TEMPLATE" "$ENV_TARGET" - chmod 600 "$ENV_TARGET" # 敏感文件建议更严格权限 - else - echo "ℹ️ 环境文件已存在,跳过生成: $ENV_TARGET" - fi -else - echo "❌ 错误:模板文件不存在: $ENV_TEMPLATE" >&2 - exit 1 -fi - -echo "✅ 所有初始化完成!" - -# 执行 Docker CMD 命令 -exec "$@" \ No newline at end of file From ea0bf051cf82061d697142520296ccf913a3e307 Mon Sep 17 00:00:00 2001 From: Cookie987 Date: Wed, 2 Apr 2025 17:02:49 +0800 Subject: [PATCH 07/16] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=92=8C=E9=95=9C=E5=83=8F=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.sh | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/run.sh b/run.sh index 2f87017b..dc2ae2b5 100644 --- a/run.sh +++ b/run.sh @@ -8,7 +8,7 @@ INSTALLER_VERSION="0.0.1-refactor" LANG=C.UTF-8 # 如无法访问GitHub请修改此处镜像地址 -GITHUB_REPO="https://github.com/MaiM-with-u/MaiBot.git" +GITHUB_REPO="https://ghfast.top/https://github.com" # 颜色输出 GREEN="\e[32m" @@ -26,7 +26,7 @@ declare -A REQUIRED_PACKAGES=( ) # 默认项目目录 -DEFAULT_INSTALL_DIR="/opt/maimbot" +DEFAULT_INSTALL_DIR="/opt/maicore" # 服务名称 SERVICE_NAME="maicore" @@ -382,8 +382,8 @@ run_installation() { # 确认安装 confirm_install() { - local confirm_msg="请确认以下信息:\n\n" - confirm_msg+="📂 安装MaiCore到: $INSTALL_DIR\n" + local confirm_msg="请确认以下更改:\n\n" + confirm_msg+="📂 安装MaiCore、Nonebot Adapter到: $INSTALL_DIR\n" confirm_msg+="🔀 分支: $BRANCH\n" [[ $IS_INSTALL_DEPENDENCIES == true ]] && confirm_msg+="📦 安装依赖:${missing_packages[@]}\n" [[ $IS_INSTALL_MONGODB == true || $IS_INSTALL_NAPCAT == true ]] && confirm_msg+="📦 安装额外组件:\n" @@ -460,19 +460,19 @@ EOF source venv/bin/activate echo -e "${GREEN}克隆MaiCore仓库...${RESET}" - git clone -b "$BRANCH" "$GITHUB_REPO" MaiBot || { + git clone -b "$BRANCH" "$GITHUB_REPO/MaiM-with-u/MaiBot" MaiBot || { echo -e "${RED}克隆MaiCore仓库失败!${RESET}" exit 1 } echo -e "${GREEN}克隆 maim_message 包仓库...${RESET}" - git clone https://github.com/MaiM-with-u/maim_message.git || { + git clone $GITHUB_REPO/MaiM-with-u/maim_message.git || { echo -e "${RED}克隆 maim_message 包仓库失败!${RESET}" exit 1 } echo -e "${GREEN}克隆 nonebot-plugin-maibot-adapters 仓库...${RESET}" - git clone https://github.com/MaiM-with-u/maim_message.git || { + git clone $GITHUB_REPO/MaiM-with-u/nonebot-plugin-maibot-adapters.git || { echo -e "${RED}克隆 nonebot-plugin-maibot-adapters 仓库失败!${RESET}" exit 1 } @@ -480,6 +480,9 @@ EOF echo -e "${GREEN}安装Python依赖...${RESET}" pip install -r MaiBot/requirements.txt + pip install nb-cli + pip install nonebot-adapter-onebot + pip install 'nonebot2[fastapi]' echo -e "${GREEN}安装maim_message依赖...${RESET}" cd maim_message @@ -509,7 +512,7 @@ EOF echo "Manually created by run.sh" > README.md mkdir src - cp -r ../../nonebot-plugin-maibot-adapters/nonebot_plugin_maibot_adapters src/plugins + cp -r ../../nonebot-plugin-maibot-adapters/nonebot_plugin_maibot_adapters src/plugins/nonebot_plugin_maibot_adapters cd .. cd .. @@ -582,7 +585,7 @@ EOF echo "INSTALL_DIR=${INSTALL_DIR}" >> /etc/maicore_install.conf echo "BRANCH=${BRANCH}" >> /etc/maicore_install.conf - whiptail --title "🎉 安装完成" --msgbox "MaiCore安装完成!\n已创建系统服务:${SERVICE_NAME},${SERVICE_NAME_WEB}\n\n使用以下命令管理服务:\n启动服务:systemctl start ${SERVICE_NAME}\n查看状态:systemctl status ${SERVICE_NAME}" 14 60 + whiptail --title "🎉 安装完成" --msgbox "MaiCore安装完成!\n已创建系统服务:${SERVICE_NAME}、${SERVICE_NAME_WEB}、${SERVICE_NAME_NBADAPTER}\n\n使用以下命令管理服务:\n启动服务:systemctl start ${SERVICE_NAME}\n查看状态:systemctl status ${SERVICE_NAME}" 14 60 } # ----------- 主执行流程 ----------- From b5e63e114e10b3e49bca0d7ae9c455c8cd90067c Mon Sep 17 00:00:00 2001 From: Cookie987 Date: Wed, 2 Apr 2025 17:09:37 +0800 Subject: [PATCH 08/16] =?UTF-8?q?fix:=20=E6=8D=A2=E6=8E=89=E4=B8=80?= =?UTF-8?q?=E5=BC=80=E5=A7=8B=E7=9A=84=E7=A5=9E=E4=BA=BA=E5=A4=9A=E5=8F=91?= =?UTF-8?q?=E8=A1=8C=E7=89=88=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit by @sourcery-ai Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- run.sh | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/run.sh b/run.sh index dc2ae2b5..1f7fba1c 100644 --- a/run.sh +++ b/run.sh @@ -216,13 +216,16 @@ run_installation() { if ! command -v whiptail &>/dev/null; then echo -e "${RED}[1/6] whiptail 未安装,正在安装...${RESET}" - # 这里的多系统适配很神人,但是能用() - - apt update && apt install -y whiptail - - pacman -S --noconfirm libnewt - - yum install -y newt + if command -v apt-get &>/dev/null; then + apt-get update && apt-get install -y whiptail + elif command -v pacman &>/dev/null; then + pacman -Syu --noconfirm whiptail + elif command -v yum &>/dev/null; then + yum install -y whiptail + else + echo -e "${RED}[Error] 无受支持的包管理器,无法安装 whiptail!${RESET}" + exit 1 + fi fi # 协议确认 From dd2bf1b7e56f9603362860ffd7e2eab719fe70fe Mon Sep 17 00:00:00 2001 From: infinitycat Date: Wed, 2 Apr 2025 20:48:26 +0800 Subject: [PATCH 09/16] =?UTF-8?q?build:=20=E6=9B=B4=E6=96=B0=20Docker=20?= =?UTF-8?q?=E9=95=9C=E5=83=8F=E6=BA=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 maimbot-adapter 镜像源从 sengokucola 更改为 maple127667 - 保持其他配置不变 --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index cf35ffec..3f86d380 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ services: adapters: container_name: maim-bot-adapters - image: sengokucola/maimbot-adapter:latest + image: maple127667/maimbot-adapter:latest environment: - TZ=Asia/Shanghai ports: From 47d788f318892833f828fadd88b4a1f05c04274f Mon Sep 17 00:00:00 2001 From: infinitycat Date: Wed, 2 Apr 2025 21:16:25 +0800 Subject: [PATCH 10/16] =?UTF-8?q?=E5=BC=83=E7=94=A8entrypoint.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 3f86d380..367d28cd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,6 +2,7 @@ services: adapters: container_name: maim-bot-adapters image: maple127667/maimbot-adapter:latest + # image: infinitycat/maimbot-adapter:latest environment: - TZ=Asia/Shanghai ports: @@ -18,6 +19,7 @@ services: core: container_name: maim-bot-core image: sengokucola/maimbot:refactor + # image: infinitycat/maimbot:refactor environment: - TZ=Asia/Shanghai # - EULA_AGREE=35362b6ea30f12891d46ef545122e84a # 同意EULA From 7b4686638c4202742449e0a798d4aa7da5d5aec3 Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Thu, 3 Apr 2025 00:30:27 +0800 Subject: [PATCH 11/16] =?UTF-8?q?fix:=E5=B0=8Fbug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/plugins/PFC/pfc.py | 33 ++++++++------------- src/plugins/storage/storage.py | 54 +++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/plugins/PFC/pfc.py b/src/plugins/PFC/pfc.py index fb7a490a..02b05dae 100644 --- a/src/plugins/PFC/pfc.py +++ b/src/plugins/PFC/pfc.py @@ -61,17 +61,14 @@ class ActionPlanner: async def plan( self, - goal: str, - method: str, + goal: str, reasoning: str, - action_history: List[Dict[str, str]] = None, - chat_observer: Optional[ChatObserver] = None, # 添加chat_observer参数 + action_history: List[Dict[str, str]] = None ) -> Tuple[str, str]: """规划下一步行动 Args: goal: 对话目标 - method: 实现方式 reasoning: 目标原因 action_history: 行动历史记录 @@ -106,7 +103,6 @@ class ActionPlanner: prompt = f"""现在你在参与一场QQ聊天,请分析以下内容,根据信息决定下一步行动: {personality_text} 当前对话目标:{goal} -实现该对话目标的方式:{method} 产生该对话目标的原因:{reasoning} {time_info} 最近的对话记录: @@ -284,10 +280,8 @@ class GoalAnalyzer: if not goal.strip() or not reasoning.strip(): logger.error(f"JSON字段内容为空,重试第{retry + 1}次") continue - - # 使用默认的方法 - method = "以友好的态度回应" - return goal, method, reasoning + + return goal, reasoning except Exception as e: logger.error(f"分析对话目标时出错: {str(e)},重试第{retry + 1}次") @@ -444,7 +438,6 @@ class ReplyGenerator: Args: goal: 对话目标 - method: 实现方式 chat_history: 聊天历史 knowledge_cache: 知识缓存 previous_reply: 上一次生成的回复(如果有) @@ -565,7 +558,6 @@ class Conversation: self.stream_id = stream_id self.state = ConversationState.INIT self.current_goal: Optional[str] = None - self.current_method: Optional[str] = None self.goal_reasoning: Optional[str] = None self.generated_reply: Optional[str] = None self.should_continue = True @@ -606,7 +598,7 @@ class Conversation: async def _conversation_loop(self): """对话循环""" # 获取最近的消息历史 - self.current_goal, self.current_method, self.goal_reasoning = await self.goal_analyzer.analyze_goal() + self.current_goal, self.goal_reasoning = await self.goal_analyzer.analyze_goal() while self.should_continue: # 执行行动 @@ -614,12 +606,15 @@ class Conversation: if not await self.chat_observer.wait_for_update(): logger.warning("等待消息更新超时") + # 如果用户最后发言时间比当前时间晚2秒,说明消息还没到数据库,跳过这次循环 + if self.chat_observer.last_user_speak_time - time.time() < 1.5: + await asyncio.sleep(1) + continue + action, reason = await self.action_planner.plan( self.current_goal, - self.current_method, self.goal_reasoning, self.action_history, # 传入action历史 - self.chat_observer # 传入chat_observer ) # 执行行动 @@ -664,13 +659,12 @@ class Conversation: messages = self.chat_observer.get_message_history(limit=30) self.generated_reply, need_replan = await self.reply_generator.generate( self.current_goal, - self.current_method, [self._convert_to_message(msg) for msg in messages], self.knowledge_cache ) if need_replan: self.state = ConversationState.RETHINKING - self.current_goal, self.current_method, self.goal_reasoning = await self.goal_analyzer.analyze_goal() + self.current_goal, self.goal_reasoning = await self.goal_analyzer.analyze_goal() else: await self._send_reply() @@ -688,19 +682,18 @@ class Conversation: self.generated_reply, need_replan = await self.reply_generator.generate( self.current_goal, - self.current_method, [self._convert_to_message(msg) for msg in messages], self.knowledge_cache ) if need_replan: self.state = ConversationState.RETHINKING - self.current_goal, self.current_method, self.goal_reasoning = await self.goal_analyzer.analyze_goal() + self.current_goal, self.goal_reasoning = await self.goal_analyzer.analyze_goal() else: await self._send_reply() elif action == "rethink_goal": self.state = ConversationState.RETHINKING - self.current_goal, self.current_method, self.goal_reasoning = await self.goal_analyzer.analyze_goal() + self.current_goal, self.goal_reasoning = await self.goal_analyzer.analyze_goal() elif action == "judge_conversation": self.state = ConversationState.JUDGING diff --git a/src/plugins/storage/storage.py b/src/plugins/storage/storage.py index c35f55be..9de5d5ee 100644 --- a/src/plugins/storage/storage.py +++ b/src/plugins/storage/storage.py @@ -1,9 +1,10 @@ -from typing import Union +from typing import Union, Optional from ...common.database import db from ..chat.message import MessageSending, MessageRecv from ..chat.chat_stream import ChatStream from src.common.logger import get_module_logger +from ..message.message_base import BaseMessageInfo, Seg, UserInfo logger = get_module_logger("message_storage") @@ -26,6 +27,57 @@ class MessageStorage: except Exception: logger.exception("存储消息失败") + async def get_last_message(self, chat_id: str, user_id: str) -> Optional[MessageRecv]: + """获取指定聊天流和用户的最后一条消息 + + Args: + chat_id: 聊天流ID + user_id: 用户ID + + Returns: + Optional[MessageRecv]: 最后一条消息,如果没有找到则返回None + """ + try: + # 查找最后一条消息 + message_data = db.messages.find_one( + { + "chat_id": chat_id, + "user_info.user_id": user_id + }, + sort=[("time", -1)] # 按时间降序排序 + ) + + if not message_data: + return None + + # 构建消息字典 + message_dict = { + "message_info": { + "platform": message_data["chat_info"]["platform"], + "message_id": message_data["message_id"], + "time": message_data["time"], + "group_info": message_data["chat_info"].get("group_info"), + "user_info": message_data["user_info"] + }, + "message_segment": { + "type": "text", + "data": message_data["processed_plain_text"] + }, + "raw_message": message_data["processed_plain_text"] + } + + # 创建并返回消息对象 + message = MessageRecv(message_dict) + message.processed_plain_text = message_data["processed_plain_text"] + message.detailed_plain_text = message_data["detailed_plain_text"] + message.update_chat_stream(ChatStream.from_dict(message_data["chat_info"])) + + return message + + except Exception: + logger.exception("获取最后一条消息失败") + return None + async def store_recalled_message(self, message_id: str, time: str, chat_stream: ChatStream) -> None: """存储撤回消息到数据库""" if "recalled_messages" not in db.list_collection_names(): From 7cd23900f35a2a171be087a5b1af3df4f28d450f Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Thu, 3 Apr 2025 00:32:46 +0800 Subject: [PATCH 12/16] fix: ruff --- src/plugins/PFC/chat_observer.py | 2 -- src/plugins/PFC/pfc.py | 10 +++------- src/plugins/PFC/reply_checker.py | 4 ++-- src/plugins/chat/bot.py | 3 --- .../chat_module/only_process/only_message_process.py | 3 --- src/plugins/storage/storage.py | 1 - 6 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/plugins/PFC/chat_observer.py b/src/plugins/PFC/chat_observer.py index f5841fd9..4fa6951e 100644 --- a/src/plugins/PFC/chat_observer.py +++ b/src/plugins/PFC/chat_observer.py @@ -1,12 +1,10 @@ import time -import datetime import asyncio from typing import Optional, Dict, Any, List from src.common.logger import get_module_logger from src.common.database import db from ..message.message_base import UserInfo from ..config.config import global_config -from ..chat.message import Message logger = get_module_logger("chat_observer") diff --git a/src/plugins/PFC/pfc.py b/src/plugins/PFC/pfc.py index 02b05dae..ca06e4c9 100644 --- a/src/plugins/PFC/pfc.py +++ b/src/plugins/PFC/pfc.py @@ -4,18 +4,14 @@ import datetime import asyncio from typing import List, Optional, Dict, Any, Tuple, Literal from enum import Enum -from src.common.database import db from src.common.logger import get_module_logger -from src.plugins.memory_system.Hippocampus import HippocampusManager from ..chat.chat_stream import ChatStream from ..message.message_base import UserInfo, Seg from ..chat.message import Message from ..models.utils_model import LLM_request from ..config.config import global_config -from src.plugins.chat.message import MessageSending, MessageRecv, MessageThinking, MessageSet -from src.plugins.chat.message_sender import message_manager +from src.plugins.chat.message import MessageSending from src.plugins.chat.chat_stream import chat_manager -from src.plugins.willing.willing_manager import willing_manager from ..message.api import global_api from ..storage.storage import MessageStorage from .chat_observer import ChatObserver @@ -467,7 +463,7 @@ class ReplyGenerator: if knowledge_cache: knowledge_text = "\n相关知识:" if isinstance(knowledge_cache, dict): - for source, content in knowledge_cache.items(): + for _source, content in knowledge_cache.items(): knowledge_text += f"\n{content}" elif isinstance(knowledge_cache, list): for item in knowledge_cache: @@ -493,7 +489,7 @@ class ReplyGenerator: 2. 体现你的性格特征 3. 自然流畅,像正常聊天一样,简短 4. 适当利用相关知识,但不要生硬引用 -{f'5. 改进上一次回复中的问题' if previous_reply else ''} +{'5. 改进上一次回复中的问题' if previous_reply else ''} 请注意把握聊天内容,不要回复的太有条理,可以有个性。请分清"你"和对方说的话,不要把"你"说的话当做对方说的话,这是你自己说的话。 请你回复的平淡一些,简短一些,说中文,不要刻意突出自身学科背景,尽量不要说你说过的话 diff --git a/src/plugins/PFC/reply_checker.py b/src/plugins/PFC/reply_checker.py index 25c81abb..3d8c743f 100644 --- a/src/plugins/PFC/reply_checker.py +++ b/src/plugins/PFC/reply_checker.py @@ -1,6 +1,6 @@ import json import datetime -from typing import Tuple, Dict, Any, List +from typing import Tuple from src.common.logger import get_module_logger from ..models.utils_model import LLM_request from ..config.config import global_config @@ -137,5 +137,5 @@ class ReplyChecker: logger.error(f"检查回复时出错: {e}") # 如果出错且已达到最大重试次数,建议重新规划 if retry_count >= self.max_retries: - return False, f"多次检查失败,建议重新规划", True + return False, "多次检查失败,建议重新规划", True return False, f"检查过程出错,建议重试: {str(e)}", False \ No newline at end of file diff --git a/src/plugins/chat/bot.py b/src/plugins/chat/bot.py index 37df41bc..9046198c 100644 --- a/src/plugins/chat/bot.py +++ b/src/plugins/chat/bot.py @@ -1,9 +1,6 @@ -from typing import Dict from ..moods.moods import MoodManager # 导入情绪管理器 from ..config.config import global_config -from ..chat_module.reasoning_chat.reasoning_generator import ResponseGenerator from .message import MessageRecv -from ..storage.storage import MessageStorage # 修改导入路径 from ..PFC.pfc import Conversation, ConversationState from .chat_stream import chat_manager from ..chat_module.only_process.only_message_process import MessageProcessor diff --git a/src/plugins/chat_module/only_process/only_message_process.py b/src/plugins/chat_module/only_process/only_message_process.py index 7684a671..4c1e7d5e 100644 --- a/src/plugins/chat_module/only_process/only_message_process.py +++ b/src/plugins/chat_module/only_process/only_message_process.py @@ -1,11 +1,8 @@ -from typing import Optional from src.common.logger import get_module_logger from src.plugins.chat.message import MessageRecv -from src.plugins.chat.chat_stream import chat_manager from src.plugins.storage.storage import MessageStorage from src.plugins.config.config import global_config import re -import asyncio from datetime import datetime logger = get_module_logger("pfc_message_processor") diff --git a/src/plugins/storage/storage.py b/src/plugins/storage/storage.py index 9de5d5ee..27888cbc 100644 --- a/src/plugins/storage/storage.py +++ b/src/plugins/storage/storage.py @@ -4,7 +4,6 @@ from ...common.database import db from ..chat.message import MessageSending, MessageRecv from ..chat.chat_stream import ChatStream from src.common.logger import get_module_logger -from ..message.message_base import BaseMessageInfo, Seg, UserInfo logger = get_module_logger("message_storage") From c1dfbaa5f288cd1b89029b4c5b800ae8db5284d6 Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Thu, 3 Apr 2025 00:34:16 +0800 Subject: [PATCH 13/16] Revert "fix: ruff" This reverts commit 7cd23900f35a2a171be087a5b1af3df4f28d450f. --- src/plugins/PFC/chat_observer.py | 2 ++ src/plugins/PFC/pfc.py | 10 +++++++--- src/plugins/PFC/reply_checker.py | 4 ++-- src/plugins/chat/bot.py | 3 +++ .../chat_module/only_process/only_message_process.py | 3 +++ src/plugins/storage/storage.py | 1 + 6 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/plugins/PFC/chat_observer.py b/src/plugins/PFC/chat_observer.py index 4fa6951e..f5841fd9 100644 --- a/src/plugins/PFC/chat_observer.py +++ b/src/plugins/PFC/chat_observer.py @@ -1,10 +1,12 @@ import time +import datetime import asyncio from typing import Optional, Dict, Any, List from src.common.logger import get_module_logger from src.common.database import db from ..message.message_base import UserInfo from ..config.config import global_config +from ..chat.message import Message logger = get_module_logger("chat_observer") diff --git a/src/plugins/PFC/pfc.py b/src/plugins/PFC/pfc.py index ca06e4c9..02b05dae 100644 --- a/src/plugins/PFC/pfc.py +++ b/src/plugins/PFC/pfc.py @@ -4,14 +4,18 @@ import datetime import asyncio from typing import List, Optional, Dict, Any, Tuple, Literal from enum import Enum +from src.common.database import db from src.common.logger import get_module_logger +from src.plugins.memory_system.Hippocampus import HippocampusManager from ..chat.chat_stream import ChatStream from ..message.message_base import UserInfo, Seg from ..chat.message import Message from ..models.utils_model import LLM_request from ..config.config import global_config -from src.plugins.chat.message import MessageSending +from src.plugins.chat.message import MessageSending, MessageRecv, MessageThinking, MessageSet +from src.plugins.chat.message_sender import message_manager from src.plugins.chat.chat_stream import chat_manager +from src.plugins.willing.willing_manager import willing_manager from ..message.api import global_api from ..storage.storage import MessageStorage from .chat_observer import ChatObserver @@ -463,7 +467,7 @@ class ReplyGenerator: if knowledge_cache: knowledge_text = "\n相关知识:" if isinstance(knowledge_cache, dict): - for _source, content in knowledge_cache.items(): + for source, content in knowledge_cache.items(): knowledge_text += f"\n{content}" elif isinstance(knowledge_cache, list): for item in knowledge_cache: @@ -489,7 +493,7 @@ class ReplyGenerator: 2. 体现你的性格特征 3. 自然流畅,像正常聊天一样,简短 4. 适当利用相关知识,但不要生硬引用 -{'5. 改进上一次回复中的问题' if previous_reply else ''} +{f'5. 改进上一次回复中的问题' if previous_reply else ''} 请注意把握聊天内容,不要回复的太有条理,可以有个性。请分清"你"和对方说的话,不要把"你"说的话当做对方说的话,这是你自己说的话。 请你回复的平淡一些,简短一些,说中文,不要刻意突出自身学科背景,尽量不要说你说过的话 diff --git a/src/plugins/PFC/reply_checker.py b/src/plugins/PFC/reply_checker.py index 3d8c743f..25c81abb 100644 --- a/src/plugins/PFC/reply_checker.py +++ b/src/plugins/PFC/reply_checker.py @@ -1,6 +1,6 @@ import json import datetime -from typing import Tuple +from typing import Tuple, Dict, Any, List from src.common.logger import get_module_logger from ..models.utils_model import LLM_request from ..config.config import global_config @@ -137,5 +137,5 @@ class ReplyChecker: logger.error(f"检查回复时出错: {e}") # 如果出错且已达到最大重试次数,建议重新规划 if retry_count >= self.max_retries: - return False, "多次检查失败,建议重新规划", True + return False, f"多次检查失败,建议重新规划", True return False, f"检查过程出错,建议重试: {str(e)}", False \ No newline at end of file diff --git a/src/plugins/chat/bot.py b/src/plugins/chat/bot.py index 9046198c..37df41bc 100644 --- a/src/plugins/chat/bot.py +++ b/src/plugins/chat/bot.py @@ -1,6 +1,9 @@ +from typing import Dict from ..moods.moods import MoodManager # 导入情绪管理器 from ..config.config import global_config +from ..chat_module.reasoning_chat.reasoning_generator import ResponseGenerator from .message import MessageRecv +from ..storage.storage import MessageStorage # 修改导入路径 from ..PFC.pfc import Conversation, ConversationState from .chat_stream import chat_manager from ..chat_module.only_process.only_message_process import MessageProcessor diff --git a/src/plugins/chat_module/only_process/only_message_process.py b/src/plugins/chat_module/only_process/only_message_process.py index 4c1e7d5e..7684a671 100644 --- a/src/plugins/chat_module/only_process/only_message_process.py +++ b/src/plugins/chat_module/only_process/only_message_process.py @@ -1,8 +1,11 @@ +from typing import Optional from src.common.logger import get_module_logger from src.plugins.chat.message import MessageRecv +from src.plugins.chat.chat_stream import chat_manager from src.plugins.storage.storage import MessageStorage from src.plugins.config.config import global_config import re +import asyncio from datetime import datetime logger = get_module_logger("pfc_message_processor") diff --git a/src/plugins/storage/storage.py b/src/plugins/storage/storage.py index 27888cbc..9de5d5ee 100644 --- a/src/plugins/storage/storage.py +++ b/src/plugins/storage/storage.py @@ -4,6 +4,7 @@ from ...common.database import db from ..chat.message import MessageSending, MessageRecv from ..chat.chat_stream import ChatStream from src.common.logger import get_module_logger +from ..message.message_base import BaseMessageInfo, Seg, UserInfo logger = get_module_logger("message_storage") From 81e791d5c7bb054f50ed6aa324af23c1fdd67a8d Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Thu, 3 Apr 2025 00:34:20 +0800 Subject: [PATCH 14/16] =?UTF-8?q?Revert=20"fix:=E5=B0=8Fbug=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7b4686638c4202742449e0a798d4aa7da5d5aec3. --- src/plugins/PFC/pfc.py | 33 +++++++++++++-------- src/plugins/storage/storage.py | 54 +--------------------------------- 2 files changed, 21 insertions(+), 66 deletions(-) diff --git a/src/plugins/PFC/pfc.py b/src/plugins/PFC/pfc.py index 02b05dae..fb7a490a 100644 --- a/src/plugins/PFC/pfc.py +++ b/src/plugins/PFC/pfc.py @@ -61,14 +61,17 @@ class ActionPlanner: async def plan( self, - goal: str, + goal: str, + method: str, reasoning: str, - action_history: List[Dict[str, str]] = None + action_history: List[Dict[str, str]] = None, + chat_observer: Optional[ChatObserver] = None, # 添加chat_observer参数 ) -> Tuple[str, str]: """规划下一步行动 Args: goal: 对话目标 + method: 实现方式 reasoning: 目标原因 action_history: 行动历史记录 @@ -103,6 +106,7 @@ class ActionPlanner: prompt = f"""现在你在参与一场QQ聊天,请分析以下内容,根据信息决定下一步行动: {personality_text} 当前对话目标:{goal} +实现该对话目标的方式:{method} 产生该对话目标的原因:{reasoning} {time_info} 最近的对话记录: @@ -280,8 +284,10 @@ class GoalAnalyzer: if not goal.strip() or not reasoning.strip(): logger.error(f"JSON字段内容为空,重试第{retry + 1}次") continue - - return goal, reasoning + + # 使用默认的方法 + method = "以友好的态度回应" + return goal, method, reasoning except Exception as e: logger.error(f"分析对话目标时出错: {str(e)},重试第{retry + 1}次") @@ -438,6 +444,7 @@ class ReplyGenerator: Args: goal: 对话目标 + method: 实现方式 chat_history: 聊天历史 knowledge_cache: 知识缓存 previous_reply: 上一次生成的回复(如果有) @@ -558,6 +565,7 @@ class Conversation: self.stream_id = stream_id self.state = ConversationState.INIT self.current_goal: Optional[str] = None + self.current_method: Optional[str] = None self.goal_reasoning: Optional[str] = None self.generated_reply: Optional[str] = None self.should_continue = True @@ -598,7 +606,7 @@ class Conversation: async def _conversation_loop(self): """对话循环""" # 获取最近的消息历史 - self.current_goal, self.goal_reasoning = await self.goal_analyzer.analyze_goal() + self.current_goal, self.current_method, self.goal_reasoning = await self.goal_analyzer.analyze_goal() while self.should_continue: # 执行行动 @@ -606,15 +614,12 @@ class Conversation: if not await self.chat_observer.wait_for_update(): logger.warning("等待消息更新超时") - # 如果用户最后发言时间比当前时间晚2秒,说明消息还没到数据库,跳过这次循环 - if self.chat_observer.last_user_speak_time - time.time() < 1.5: - await asyncio.sleep(1) - continue - action, reason = await self.action_planner.plan( self.current_goal, + self.current_method, self.goal_reasoning, self.action_history, # 传入action历史 + self.chat_observer # 传入chat_observer ) # 执行行动 @@ -659,12 +664,13 @@ class Conversation: messages = self.chat_observer.get_message_history(limit=30) self.generated_reply, need_replan = await self.reply_generator.generate( self.current_goal, + self.current_method, [self._convert_to_message(msg) for msg in messages], self.knowledge_cache ) if need_replan: self.state = ConversationState.RETHINKING - self.current_goal, self.goal_reasoning = await self.goal_analyzer.analyze_goal() + self.current_goal, self.current_method, self.goal_reasoning = await self.goal_analyzer.analyze_goal() else: await self._send_reply() @@ -682,18 +688,19 @@ class Conversation: self.generated_reply, need_replan = await self.reply_generator.generate( self.current_goal, + self.current_method, [self._convert_to_message(msg) for msg in messages], self.knowledge_cache ) if need_replan: self.state = ConversationState.RETHINKING - self.current_goal, self.goal_reasoning = await self.goal_analyzer.analyze_goal() + self.current_goal, self.current_method, self.goal_reasoning = await self.goal_analyzer.analyze_goal() else: await self._send_reply() elif action == "rethink_goal": self.state = ConversationState.RETHINKING - self.current_goal, self.goal_reasoning = await self.goal_analyzer.analyze_goal() + self.current_goal, self.current_method, self.goal_reasoning = await self.goal_analyzer.analyze_goal() elif action == "judge_conversation": self.state = ConversationState.JUDGING diff --git a/src/plugins/storage/storage.py b/src/plugins/storage/storage.py index 9de5d5ee..c35f55be 100644 --- a/src/plugins/storage/storage.py +++ b/src/plugins/storage/storage.py @@ -1,10 +1,9 @@ -from typing import Union, Optional +from typing import Union from ...common.database import db from ..chat.message import MessageSending, MessageRecv from ..chat.chat_stream import ChatStream from src.common.logger import get_module_logger -from ..message.message_base import BaseMessageInfo, Seg, UserInfo logger = get_module_logger("message_storage") @@ -27,57 +26,6 @@ class MessageStorage: except Exception: logger.exception("存储消息失败") - async def get_last_message(self, chat_id: str, user_id: str) -> Optional[MessageRecv]: - """获取指定聊天流和用户的最后一条消息 - - Args: - chat_id: 聊天流ID - user_id: 用户ID - - Returns: - Optional[MessageRecv]: 最后一条消息,如果没有找到则返回None - """ - try: - # 查找最后一条消息 - message_data = db.messages.find_one( - { - "chat_id": chat_id, - "user_info.user_id": user_id - }, - sort=[("time", -1)] # 按时间降序排序 - ) - - if not message_data: - return None - - # 构建消息字典 - message_dict = { - "message_info": { - "platform": message_data["chat_info"]["platform"], - "message_id": message_data["message_id"], - "time": message_data["time"], - "group_info": message_data["chat_info"].get("group_info"), - "user_info": message_data["user_info"] - }, - "message_segment": { - "type": "text", - "data": message_data["processed_plain_text"] - }, - "raw_message": message_data["processed_plain_text"] - } - - # 创建并返回消息对象 - message = MessageRecv(message_dict) - message.processed_plain_text = message_data["processed_plain_text"] - message.detailed_plain_text = message_data["detailed_plain_text"] - message.update_chat_stream(ChatStream.from_dict(message_data["chat_info"])) - - return message - - except Exception: - logger.exception("获取最后一条消息失败") - return None - async def store_recalled_message(self, message_id: str, time: str, chat_stream: ChatStream) -> None: """存储撤回消息到数据库""" if "recalled_messages" not in db.list_collection_names(): From 9f2fd2bd50b208b4e7b0637e609848977152c6de Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Thu, 3 Apr 2025 00:37:24 +0800 Subject: [PATCH 15/16] ruff:fix --- src/plugins/PFC/chat_observer.py | 2 -- src/plugins/PFC/pfc.py | 10 +++------- src/plugins/PFC/reply_checker.py | 4 ++-- src/plugins/chat/bot.py | 3 --- .../chat_module/only_process/only_message_process.py | 3 --- 5 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/plugins/PFC/chat_observer.py b/src/plugins/PFC/chat_observer.py index f5841fd9..4fa6951e 100644 --- a/src/plugins/PFC/chat_observer.py +++ b/src/plugins/PFC/chat_observer.py @@ -1,12 +1,10 @@ import time -import datetime import asyncio from typing import Optional, Dict, Any, List from src.common.logger import get_module_logger from src.common.database import db from ..message.message_base import UserInfo from ..config.config import global_config -from ..chat.message import Message logger = get_module_logger("chat_observer") diff --git a/src/plugins/PFC/pfc.py b/src/plugins/PFC/pfc.py index fb7a490a..667a6f03 100644 --- a/src/plugins/PFC/pfc.py +++ b/src/plugins/PFC/pfc.py @@ -4,18 +4,14 @@ import datetime import asyncio from typing import List, Optional, Dict, Any, Tuple, Literal from enum import Enum -from src.common.database import db from src.common.logger import get_module_logger -from src.plugins.memory_system.Hippocampus import HippocampusManager from ..chat.chat_stream import ChatStream from ..message.message_base import UserInfo, Seg from ..chat.message import Message from ..models.utils_model import LLM_request from ..config.config import global_config -from src.plugins.chat.message import MessageSending, MessageRecv, MessageThinking, MessageSet -from src.plugins.chat.message_sender import message_manager +from src.plugins.chat.message import MessageSending from src.plugins.chat.chat_stream import chat_manager -from src.plugins.willing.willing_manager import willing_manager from ..message.api import global_api from ..storage.storage import MessageStorage from .chat_observer import ChatObserver @@ -474,7 +470,7 @@ class ReplyGenerator: if knowledge_cache: knowledge_text = "\n相关知识:" if isinstance(knowledge_cache, dict): - for source, content in knowledge_cache.items(): + for _source, content in knowledge_cache.items(): knowledge_text += f"\n{content}" elif isinstance(knowledge_cache, list): for item in knowledge_cache: @@ -500,7 +496,7 @@ class ReplyGenerator: 2. 体现你的性格特征 3. 自然流畅,像正常聊天一样,简短 4. 适当利用相关知识,但不要生硬引用 -{f'5. 改进上一次回复中的问题' if previous_reply else ''} +{'5. 改进上一次回复中的问题' if previous_reply else ''} 请注意把握聊天内容,不要回复的太有条理,可以有个性。请分清"你"和对方说的话,不要把"你"说的话当做对方说的话,这是你自己说的话。 请你回复的平淡一些,简短一些,说中文,不要刻意突出自身学科背景,尽量不要说你说过的话 diff --git a/src/plugins/PFC/reply_checker.py b/src/plugins/PFC/reply_checker.py index 25c81abb..3d8c743f 100644 --- a/src/plugins/PFC/reply_checker.py +++ b/src/plugins/PFC/reply_checker.py @@ -1,6 +1,6 @@ import json import datetime -from typing import Tuple, Dict, Any, List +from typing import Tuple from src.common.logger import get_module_logger from ..models.utils_model import LLM_request from ..config.config import global_config @@ -137,5 +137,5 @@ class ReplyChecker: logger.error(f"检查回复时出错: {e}") # 如果出错且已达到最大重试次数,建议重新规划 if retry_count >= self.max_retries: - return False, f"多次检查失败,建议重新规划", True + return False, "多次检查失败,建议重新规划", True return False, f"检查过程出错,建议重试: {str(e)}", False \ No newline at end of file diff --git a/src/plugins/chat/bot.py b/src/plugins/chat/bot.py index 37df41bc..9046198c 100644 --- a/src/plugins/chat/bot.py +++ b/src/plugins/chat/bot.py @@ -1,9 +1,6 @@ -from typing import Dict from ..moods.moods import MoodManager # 导入情绪管理器 from ..config.config import global_config -from ..chat_module.reasoning_chat.reasoning_generator import ResponseGenerator from .message import MessageRecv -from ..storage.storage import MessageStorage # 修改导入路径 from ..PFC.pfc import Conversation, ConversationState from .chat_stream import chat_manager from ..chat_module.only_process.only_message_process import MessageProcessor diff --git a/src/plugins/chat_module/only_process/only_message_process.py b/src/plugins/chat_module/only_process/only_message_process.py index 7684a671..4c1e7d5e 100644 --- a/src/plugins/chat_module/only_process/only_message_process.py +++ b/src/plugins/chat_module/only_process/only_message_process.py @@ -1,11 +1,8 @@ -from typing import Optional from src.common.logger import get_module_logger from src.plugins.chat.message import MessageRecv -from src.plugins.chat.chat_stream import chat_manager from src.plugins.storage.storage import MessageStorage from src.plugins.config.config import global_config import re -import asyncio from datetime import datetime logger = get_module_logger("pfc_message_processor") From 30d470d9f517545ee01e5738a504ac6554fbd67a Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Thu, 3 Apr 2025 11:07:10 +0800 Subject: [PATCH 16/16] =?UTF-8?q?fix:=E5=B0=9D=E8=AF=95=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=82=B8=E9=A3=9E=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- run.sh => scripts/run.sh | 0 src/plugins/models/utils_model.py | 323 +++++++++++++++++------------- 2 files changed, 181 insertions(+), 142 deletions(-) rename run.sh => scripts/run.sh (100%) diff --git a/run.sh b/scripts/run.sh similarity index 100% rename from run.sh rename to scripts/run.sh diff --git a/src/plugins/models/utils_model.py b/src/plugins/models/utils_model.py index 263e1161..260c5f5a 100644 --- a/src/plugins/models/utils_model.py +++ b/src/plugins/models/utils_model.py @@ -198,156 +198,195 @@ class LLM_request: headers["Accept"] = "text/event-stream" async with aiohttp.ClientSession() as session: - async with session.post(api_url, headers=headers, json=payload) as response: - # 处理需要重试的状态码 - if response.status in policy["retry_codes"]: - wait_time = policy["base_wait"] * (2**retry) - logger.warning(f"错误码: {response.status}, 等待 {wait_time}秒后重试") - if response.status == 413: - logger.warning("请求体过大,尝试压缩...") - image_base64 = compress_base64_image_by_scale(image_base64) - payload = await self._build_payload(prompt, image_base64, image_format) - elif response.status in [500, 503]: - logger.error(f"错误码: {response.status} - {error_code_mapping.get(response.status)}") - raise RuntimeError("服务器负载过高,模型恢复失败QAQ") - else: - logger.warning(f"请求限制(429),等待{wait_time}秒后重试...") - - await asyncio.sleep(wait_time) - continue - elif response.status in policy["abort_codes"]: - logger.error(f"错误码: {response.status} - {error_code_mapping.get(response.status)}") - # 尝试获取并记录服务器返回的详细错误信息 - try: - error_json = await response.json() - if error_json and isinstance(error_json, list) and len(error_json) > 0: - for error_item in error_json: - if "error" in error_item and isinstance(error_item["error"], dict): - error_obj = error_item["error"] - error_code = error_obj.get("code") - error_message = error_obj.get("message") - error_status = error_obj.get("status") - logger.error( - f"服务器错误详情: 代码={error_code}, 状态={error_status}, " - f"消息={error_message}" - ) - elif isinstance(error_json, dict) and "error" in error_json: - # 处理单个错误对象的情况 - error_obj = error_json.get("error", {}) - error_code = error_obj.get("code") - error_message = error_obj.get("message") - error_status = error_obj.get("status") - logger.error( - f"服务器错误详情: 代码={error_code}, 状态={error_status}, 消息={error_message}" - ) + try: + async with session.post(api_url, headers=headers, json=payload) as response: + # 处理需要重试的状态码 + if response.status in policy["retry_codes"]: + wait_time = policy["base_wait"] * (2**retry) + logger.warning(f"错误码: {response.status}, 等待 {wait_time}秒后重试") + if response.status == 413: + logger.warning("请求体过大,尝试压缩...") + image_base64 = compress_base64_image_by_scale(image_base64) + payload = await self._build_payload(prompt, image_base64, image_format) + elif response.status in [500, 503]: + logger.error(f"错误码: {response.status} - {error_code_mapping.get(response.status)}") + raise RuntimeError("服务器负载过高,模型恢复失败QAQ") else: - # 记录原始错误响应内容 - logger.error(f"服务器错误响应: {error_json}") - except Exception as e: - logger.warning(f"无法解析服务器错误响应: {str(e)}") + logger.warning(f"请求限制(429),等待{wait_time}秒后重试...") - if response.status == 403: - # 只针对硅基流动的V3和R1进行降级处理 - if ( - self.model_name.startswith("Pro/deepseek-ai") - and self.base_url == "https://api.siliconflow.cn/v1/" - ): - old_model_name = self.model_name - self.model_name = self.model_name[4:] # 移除"Pro/"前缀 - logger.warning(f"检测到403错误,模型从 {old_model_name} 降级为 {self.model_name}") - - # 对全局配置进行更新 - if global_config.llm_normal.get("name") == old_model_name: - global_config.llm_normal["name"] = self.model_name - logger.warning(f"将全局配置中的 llm_normal 模型临时降级至{self.model_name}") - - if global_config.llm_reasoning.get("name") == old_model_name: - global_config.llm_reasoning["name"] = self.model_name - logger.warning(f"将全局配置中的 llm_reasoning 模型临时降级至{self.model_name}") - - # 更新payload中的模型名 - if payload and "model" in payload: - payload["model"] = self.model_name - - # 重新尝试请求 - retry -= 1 # 不计入重试次数 - continue - - raise RuntimeError(f"请求被拒绝: {error_code_mapping.get(response.status)}") - - response.raise_for_status() - reasoning_content = "" - - # 将流式输出转化为非流式输出 - if stream_mode: - flag_delta_content_finished = False - accumulated_content = "" - usage = None # 初始化usage变量,避免未定义错误 - - async for line_bytes in response.content: + await asyncio.sleep(wait_time) + continue + elif response.status in policy["abort_codes"]: + logger.error(f"错误码: {response.status} - {error_code_mapping.get(response.status)}") + # 尝试获取并记录服务器返回的详细错误信息 try: - line = line_bytes.decode("utf-8").strip() - if not line: + error_json = await response.json() + if error_json and isinstance(error_json, list) and len(error_json) > 0: + for error_item in error_json: + if "error" in error_item and isinstance(error_item["error"], dict): + error_obj = error_item["error"] + error_code = error_obj.get("code") + error_message = error_obj.get("message") + error_status = error_obj.get("status") + logger.error( + f"服务器错误详情: 代码={error_code}, 状态={error_status}, " + f"消息={error_message}" + ) + elif isinstance(error_json, dict) and "error" in error_json: + # 处理单个错误对象的情况 + error_obj = error_json.get("error", {}) + error_code = error_obj.get("code") + error_message = error_obj.get("message") + error_status = error_obj.get("status") + logger.error( + f"服务器错误详情: 代码={error_code}, 状态={error_status}, 消息={error_message}" + ) + else: + # 记录原始错误响应内容 + logger.error(f"服务器错误响应: {error_json}") + except Exception as e: + logger.warning(f"无法解析服务器错误响应: {str(e)}") + + if response.status == 403: + # 只针对硅基流动的V3和R1进行降级处理 + if ( + self.model_name.startswith("Pro/deepseek-ai") + and self.base_url == "https://api.siliconflow.cn/v1/" + ): + old_model_name = self.model_name + self.model_name = self.model_name[4:] # 移除"Pro/"前缀 + logger.warning(f"检测到403错误,模型从 {old_model_name} 降级为 {self.model_name}") + + # 对全局配置进行更新 + if global_config.llm_normal.get("name") == old_model_name: + global_config.llm_normal["name"] = self.model_name + logger.warning(f"将全局配置中的 llm_normal 模型临时降级至{self.model_name}") + + if global_config.llm_reasoning.get("name") == old_model_name: + global_config.llm_reasoning["name"] = self.model_name + logger.warning(f"将全局配置中的 llm_reasoning 模型临时降级至{self.model_name}") + + # 更新payload中的模型名 + if payload and "model" in payload: + payload["model"] = self.model_name + + # 重新尝试请求 + retry -= 1 # 不计入重试次数 continue - if line.startswith("data:"): - data_str = line[5:].strip() - if data_str == "[DONE]": - break - try: - chunk = json.loads(data_str) - if flag_delta_content_finished: - chunk_usage = chunk.get("usage", None) - if chunk_usage: - usage = chunk_usage # 获取token用量 - else: - delta = chunk["choices"][0]["delta"] - delta_content = delta.get("content") - if delta_content is None: - delta_content = "" - accumulated_content += delta_content - # 检测流式输出文本是否结束 - finish_reason = chunk["choices"][0].get("finish_reason") - if delta.get("reasoning_content", None): - reasoning_content += delta["reasoning_content"] - if finish_reason == "stop": + + raise RuntimeError(f"请求被拒绝: {error_code_mapping.get(response.status)}") + + response.raise_for_status() + reasoning_content = "" + + # 将流式输出转化为非流式输出 + if stream_mode: + flag_delta_content_finished = False + accumulated_content = "" + usage = None # 初始化usage变量,避免未定义错误 + + async for line_bytes in response.content: + try: + line = line_bytes.decode("utf-8").strip() + if not line: + continue + if line.startswith("data:"): + data_str = line[5:].strip() + if data_str == "[DONE]": + break + try: + chunk = json.loads(data_str) + if flag_delta_content_finished: chunk_usage = chunk.get("usage", None) if chunk_usage: - usage = chunk_usage - break - # 部分平台在文本输出结束前不会返回token用量,此时需要再获取一次chunk - flag_delta_content_finished = True + usage = chunk_usage # 获取token用量 + else: + delta = chunk["choices"][0]["delta"] + delta_content = delta.get("content") + if delta_content is None: + delta_content = "" + accumulated_content += delta_content + # 检测流式输出文本是否结束 + finish_reason = chunk["choices"][0].get("finish_reason") + if delta.get("reasoning_content", None): + reasoning_content += delta["reasoning_content"] + if finish_reason == "stop": + chunk_usage = chunk.get("usage", None) + if chunk_usage: + usage = chunk_usage + break + # 部分平台在文本输出结束前不会返回token用量,此时需要再获取一次chunk + flag_delta_content_finished = True - except Exception as e: - logger.exception(f"解析流式输出错误: {str(e)}") - except GeneratorExit: - logger.warning("流式输出被中断") - break - except Exception as e: - logger.error(f"处理流式输出时发生错误: {str(e)}") - break - content = accumulated_content - think_match = re.search(r"(.*?)", content, re.DOTALL) - if think_match: - reasoning_content = think_match.group(1).strip() - content = re.sub(r".*?", "", content, flags=re.DOTALL).strip() - # 构造一个伪result以便调用自定义响应处理器或默认处理器 - result = { - "choices": [{"message": {"content": content, "reasoning_content": reasoning_content}}], - "usage": usage, - } - return ( - response_handler(result) - if response_handler - else self._default_response_handler(result, user_id, request_type, endpoint) - ) + except Exception as e: + logger.exception(f"解析流式输出错误: {str(e)}") + except GeneratorExit: + logger.warning("流式输出被中断,正在清理资源...") + # 确保资源被正确清理 + await response.release() + # 返回已经累积的内容 + result = { + "choices": [{"message": {"content": accumulated_content, "reasoning_content": reasoning_content}}], + "usage": usage, + } + return ( + response_handler(result) + if response_handler + else self._default_response_handler(result, user_id, request_type, endpoint) + ) + except Exception as e: + logger.error(f"处理流式输出时发生错误: {str(e)}") + # 确保在发生错误时也能正确清理资源 + try: + await response.release() + except Exception as cleanup_error: + logger.error(f"清理资源时发生错误: {cleanup_error}") + # 返回已经累积的内容 + result = { + "choices": [{"message": {"content": accumulated_content, "reasoning_content": reasoning_content}}], + "usage": usage, + } + return ( + response_handler(result) + if response_handler + else self._default_response_handler(result, user_id, request_type, endpoint) + ) + content = accumulated_content + think_match = re.search(r"(.*?)", content, re.DOTALL) + if think_match: + reasoning_content = think_match.group(1).strip() + content = re.sub(r".*?", "", content, flags=re.DOTALL).strip() + # 构造一个伪result以便调用自定义响应处理器或默认处理器 + result = { + "choices": [{"message": {"content": content, "reasoning_content": reasoning_content}}], + "usage": usage, + } + return ( + response_handler(result) + if response_handler + else self._default_response_handler(result, user_id, request_type, endpoint) + ) + else: + result = await response.json() + # 使用自定义处理器或默认处理 + return ( + response_handler(result) + if response_handler + else self._default_response_handler(result, user_id, request_type, endpoint) + ) + + except (aiohttp.ClientError, asyncio.TimeoutError) as e: + if retry < policy["max_retries"] - 1: + wait_time = policy["base_wait"] * (2**retry) + logger.error(f"网络错误,等待{wait_time}秒后重试... 错误: {str(e)}") + await asyncio.sleep(wait_time) + continue else: - result = await response.json() - # 使用自定义处理器或默认处理 - return ( - response_handler(result) - if response_handler - else self._default_response_handler(result, user_id, request_type, endpoint) - ) + logger.critical(f"网络错误达到最大重试次数: {str(e)}") + raise RuntimeError(f"网络请求失败: {str(e)}") from e + except Exception as e: + logger.critical(f"未预期的错误: {str(e)}") + raise RuntimeError(f"请求过程中发生错误: {str(e)}") from e except aiohttp.ClientResponseError as e: # 处理aiohttp抛出的响应错误