diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..d30b0e651 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,48 @@ +# MaiMBot 开发指南 + +## 🛠️ 常用命令 + +- **运行机器人**: `python run.py` 或 `python bot.py` +- **安装依赖**: `pip install --upgrade -r requirements.txt` +- **Docker 部署**: `docker-compose up` +- **代码检查**: `ruff check .` +- **代码格式化**: `ruff format .` +- **内存可视化**: `run_memory_vis.bat` 或 `python -m src.plugins.memory_system.draw_memory` +- **推理过程可视化**: `script/run_thingking.bat` + +## 🔧 脚本工具 + +- **运行MongoDB**: `script/run_db.bat` - 在端口27017启动MongoDB +- **Windows完整启动**: `script/run_windows.bat` - 检查Python版本、设置虚拟环境、安装依赖并运行机器人 +- **快速启动**: `script/run_maimai.bat` - 设置UTF-8编码并执行"nb run"命令 + +## 📝 代码风格 + +- **Python版本**: 3.9+ +- **行长度限制**: 88字符 +- **命名规范**: + - `snake_case` 用于函数和变量 + - `PascalCase` 用于类 + - `_prefix` 用于私有成员 +- **导入顺序**: 标准库 → 第三方库 → 本地模块 +- **异步编程**: 对I/O操作使用async/await +- **日志记录**: 使用loguru进行一致的日志记录 +- **错误处理**: 使用带有具体异常的try/except +- **文档**: 为类和公共函数编写docstrings + +## 🧩 系统架构 + +- **框架**: NoneBot2框架与插件架构 +- **数据库**: MongoDB持久化存储 +- **设计模式**: 工厂模式和单例管理器 +- **配置管理**: 使用环境变量和TOML文件 +- **内存系统**: 基于图的记忆结构,支持记忆构建、压缩、检索和遗忘 +- **情绪系统**: 情绪模拟与概率权重 +- **LLM集成**: 支持多个LLM服务提供商(ChatAnywhere, SiliconFlow, DeepSeek) + +## ⚙️ 环境配置 + +- 使用`template.env`作为环境变量模板 +- 使用`template/bot_config_template.toml`作为机器人配置模板 +- MongoDB配置: 主机、端口、数据库名 +- API密钥配置: 各LLM提供商的API密钥 diff --git a/README.md b/README.md index f919e8902..5fddcb320 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -# 麦麦!MaiMBot (编辑中) - +# 麦麦!MaiMBot (编辑中)
@@ -45,7 +44,6 @@ - (由 [CabLate](https://github.com/cablate) 贡献) [Telegram 与其他平台(未来可能会有)的版本](https://github.com/cablate/MaiMBot/tree/telegram) - [集中讨论串](https://github.com/SengokuCola/MaiMBot/discussions/149) -##

📚 文档 ⬇️ 快速开始使用麦麦 ⬇️

@@ -54,6 +52,7 @@ - 📦 **Windows 一键傻瓜式部署**:请运行项目根目录中的 `run.bat`,部署完成后请参照后续配置指南进行配置 + - [📦 Windows 手动部署指南 ](docs/manual_deploy_windows.md) - [📦 Linux 手动部署指南 ](docs/manual_deploy_linux.md) @@ -63,7 +62,9 @@ - [🐳 Docker部署指南](docs/docker_deploy.md) + ### 配置说明 + - [🎀 新手配置指南](docs/installation_cute.md) - 通俗易懂的配置教程,适合初次使用的猫娘 - [⚙️ 标准配置指南](docs/installation_standard.md) - 简明专业的配置说明,适合有经验的用户 @@ -76,6 +77,7 @@ ## 🎯 功能介绍 ### 💬 聊天功能 + - 支持关键词检索主动发言:对消息的话题topic进行识别,如果检测到麦麦存储过的话题就会主动进行发言 - 支持bot名字呼唤发言:检测到"麦麦"会主动发言,可配置 - 支持多模型,多厂商自定义配置 @@ -84,31 +86,33 @@ - 错别字和多条回复功能:麦麦可以随机生成错别字,会多条发送回复以及对消息进行reply ### 😊 表情包功能 + - 支持根据发言内容发送对应情绪的表情包 - 会自动偷群友的表情包 ### 📅 日程功能 + - 麦麦会自动生成一天的日程,实现更拟人的回复 ### 🧠 记忆功能 + - 对聊天记录进行概括存储,在需要时调用,待完善 ### 📚 知识库功能 + - 基于embedding模型的知识库,手动放入txt会自动识别,写完了,暂时禁用 ### 👥 关系功能 + - 针对每个用户创建"关系",可以对不同用户进行个性化回复,目前只有极其简单的好感度(WIP) - 针对每个群创建"群印象",可以对不同群进行个性化回复(WIP) - - ## 开发计划TODO:LIST 规划主线 0.6.0:记忆系统更新 0.7.0: 麦麦RunTime - - 人格功能:WIP - 群氛围功能:WIP - 图片发送,转发功能:WIP @@ -128,7 +132,6 @@ - 采用截断生成加快麦麦的反应速度 - 改进发送消息的触发 - ## 设计理念 - **千石可乐说:** @@ -138,7 +141,6 @@ - 如果人类真的需要一个AI来陪伴自己,并不是所有人都需要一个完美的,能解决所有问题的helpful assistant,而是一个会犯错的,拥有自己感知和想法的"生命形式"。 - 代码会保持开源和开放,但个人希望MaiMbot的运行时数据保持封闭,尽量避免以显式命令来对其进行控制和调试.我认为一个你无法完全掌控的个体才更能让你感觉到它的自主性,而视其成为一个对话机器. - ## 📌 注意事项 SengokuCola~~纯编程外行,面向cursor编程,很多代码写得不好多多包涵~~已得到大脑升级 @@ -146,6 +148,7 @@ SengokuCola~~纯编程外行,面向cursor编程,很多代码写得不好多 > 本应用生成内容来自人工智能模型,由 AI 生成,请仔细甄别,请勿用于违反法律的用途,AI生成内容不代表本人观点和立场。 ## 致谢 + [nonebot2](https://github.com/nonebot/nonebot2): 跨平台 Python 异步聊天机器人框架 [NapCat](https://github.com/NapNeko/NapCatQQ): 现代化的基于 NTQQ 的 Bot 协议端实现 @@ -157,6 +160,6 @@ SengokuCola~~纯编程外行,面向cursor编程,很多代码写得不好多 - ## Stargazers over time + [![Stargazers over time](https://starchart.cc/SengokuCola/MaiMBot.svg?variant=adaptive)](https://starchart.cc/SengokuCola/MaiMBot) diff --git a/docs/doc1.md b/docs/doc1.md index 158136b9c..e8aa0f0d6 100644 --- a/docs/doc1.md +++ b/docs/doc1.md @@ -1,6 +1,7 @@ # 📂 文件及功能介绍 (2025年更新) ## 根目录 + - **README.md**: 项目的概述和使用说明。 - **requirements.txt**: 项目所需的Python依赖包列表。 - **bot.py**: 主启动文件,负责环境配置加载和NoneBot初始化。 @@ -10,6 +11,7 @@ - **run_*.bat**: 各种启动脚本,包括数据库、maimai和thinking功能。 ## `src/` 目录结构 + - **`plugins/` 目录**: 存放不同功能模块的插件。 - **chat/**: 处理聊天相关的功能,如消息发送和接收。 - **memory_system/**: 处理机器人的记忆功能。 @@ -22,94 +24,96 @@ - **`common/` 目录**: 存放通用的工具和库。 - **database.py**: 处理与数据库的交互,负责数据的存储和检索。 - - **__init__.py**: 初始化模块。 + - ****init**.py**: 初始化模块。 ## `config/` 目录 + - **bot_config_template.toml**: 机器人配置模板。 - **auto_format.py**: 自动格式化工具。 ### `src/plugins/chat/` 目录文件详细介绍 -1. **`__init__.py`**: +1. **`__init__.py`**: - 初始化 `chat` 模块,使其可以作为一个包被导入。 -2. **`bot.py`**: +2. **`bot.py`**: - 主要的聊天机器人逻辑实现,处理消息的接收、思考和回复。 - 包含 `ChatBot` 类,负责消息处理流程控制。 - 集成记忆系统和意愿管理。 -3. **`config.py`**: +3. **`config.py`**: - 配置文件,定义了聊天机器人的各种参数和设置。 - 包含 `BotConfig` 和全局配置对象 `global_config`。 -4. **`cq_code.py`**: +4. **`cq_code.py`**: - 处理 CQ 码(CoolQ 码),用于发送和接收特定格式的消息。 -5. **`emoji_manager.py`**: +5. **`emoji_manager.py`**: - 管理表情包的发送和接收,根据情感选择合适的表情。 - 提供根据情绪获取表情的方法。 -6. **`llm_generator.py`**: +6. **`llm_generator.py`**: - 生成基于大语言模型的回复,处理用户输入并生成相应的文本。 - 通过 `ResponseGenerator` 类实现回复生成。 -7. **`message.py`**: +7. **`message.py`**: - 定义消息的结构和处理逻辑,包含多种消息类型: - `Message`: 基础消息类 - `MessageSet`: 消息集合 - `Message_Sending`: 发送中的消息 - `Message_Thinking`: 思考状态的消息 -8. **`message_sender.py`**: +8. **`message_sender.py`**: - 控制消息的发送逻辑,确保消息按照特定规则发送。 - 包含 `message_manager` 对象,用于管理消息队列。 -9. **`prompt_builder.py`**: +9. **`prompt_builder.py`**: - 构建用于生成回复的提示,优化机器人的响应质量。 -10. **`relationship_manager.py`**: +10. **`relationship_manager.py`**: - 管理用户之间的关系,记录用户的互动和偏好。 - 提供更新关系和关系值的方法。 -11. **`Segment_builder.py`**: +11. **`Segment_builder.py`**: - 构建消息片段的工具。 -12. **`storage.py`**: +12. **`storage.py`**: - 处理数据存储,负责将聊天记录和用户信息保存到数据库。 - 实现 `MessageStorage` 类管理消息存储。 -13. **`thinking_idea.py`**: +13. **`thinking_idea.py`**: - 实现机器人的思考机制。 -14. **`topic_identifier.py`**: +14. **`topic_identifier.py`**: - 识别消息中的主题,帮助机器人理解用户的意图。 -15. **`utils.py`** 和 **`utils_*.py`** 系列文件: +15. **`utils.py`** 和 **`utils_*.py`** 系列文件: - 存放各种工具函数,提供辅助功能以支持其他模块。 - 包括 `utils_cq.py`、`utils_image.py`、`utils_user.py` 等专门工具。 -16. **`willing_manager.py`**: +16. **`willing_manager.py`**: - 管理机器人的回复意愿,动态调整回复概率。 - 通过多种因素(如被提及、话题兴趣度)影响回复决策。 ### `src/plugins/memory_system/` 目录文件介绍 -1. **`memory.py`**: +1. **`memory.py`**: - 实现记忆管理核心功能,包含 `memory_graph` 对象。 - 提供相关项目检索,支持多层次记忆关联。 -2. **`draw_memory.py`**: +2. **`draw_memory.py`**: - 记忆可视化工具。 -3. **`memory_manual_build.py`**: +3. **`memory_manual_build.py`**: - 手动构建记忆的工具。 -4. **`offline_llm.py`**: +4. **`offline_llm.py`**: - 离线大语言模型处理功能。 ## 消息处理流程 ### 1. 消息接收与预处理 + - 通过 `ChatBot.handle_message()` 接收群消息。 - 进行用户和群组的权限检查。 - 更新用户关系信息。 @@ -117,12 +121,14 @@ - 对消息进行过滤和敏感词检测。 ### 2. 主题识别与决策 + - 使用 `topic_identifier` 识别消息主题。 - 通过记忆系统检查对主题的兴趣度。 - `willing_manager` 动态计算回复概率。 - 根据概率决定是否回复消息。 ### 3. 回复生成与发送 + - 如需回复,首先创建 `Message_Thinking` 对象表示思考状态。 - 调用 `ResponseGenerator.generate_response()` 生成回复内容和情感状态。 - 删除思考消息,创建 `MessageSet` 准备发送回复。 diff --git a/docs/docker_deploy.md b/docs/docker_deploy.md index db759dfd0..f78f73dca 100644 --- a/docs/docker_deploy.md +++ b/docs/docker_deploy.md @@ -20,7 +20,6 @@ wget https://raw.githubusercontent.com/SengokuCola/MaiMBot/main/docker-compose.y - 若需要启用MongoDB数据库的用户名和密码,可进入docker-compose.yml,取消MongoDB处的注释并修改变量旁 `=` 后方的值为你的用户名和密码\ 修改后请注意在之后配置 `.env.prod` 文件时指定MongoDB数据库的用户名密码 - ### 2. 启动服务 - **!!! 请在第一次启动前确保当前工作目录下 `.env.prod` 与 `bot_config.toml` 文件存在 !!!**\ @@ -42,8 +41,8 @@ NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker-compose up -d ### 3. 修改配置并重启Docker -- 请前往 [🎀新手配置指南](./installation_cute.md) 或 [⚙️标准配置指南](./installation_standard.md) 完成 `.env.prod` 与 `bot_config.toml` 配置文件的编写\ -**需要注意 `.env.prod` 中HOST处IP的填写,Docker中部署和系统中直接安装的配置会有所不同** +- 请前往 [🎀 新手配置指南](docs/installation_cute.md) 或 [⚙️ 标准配置指南](docs/installation_standard.md) 完成`.env.prod`与`bot_config.toml`配置文件的编写\ +**需要注意`.env.prod`中HOST处IP的填写,Docker中部署和系统中直接安装的配置会有所不同** - 重启Docker容器: @@ -59,7 +58,6 @@ NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker compose restart NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker-compose restart ``` - ### 4. 登入NapCat管理页添加反向WebSocket - 在浏览器地址栏输入 `http://<宿主机IP>:6099/` 进入NapCat的管理Web页,添加一个Websocket客户端 @@ -69,7 +67,6 @@ NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker-compose restart - Websocket客户端的名称自定,URL栏填入 `ws://maimbot:8080/onebot/v11/ws`,启用并保存即可\ (若修改过容器名称则替换maimbot为你自定的名称) - ### 5. 部署完成,愉快地和麦麦对话吧! @@ -89,9 +86,8 @@ NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker compose up -d NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker-compose up -d ``` - ## ⚠️ 注意事项 - 目前部署方案仍在测试中,可能存在未知问题 - 配置文件中的API密钥请妥善保管,不要泄露 -- 建议先在测试环境中运行,确认无误后再部署到生产环境 \ No newline at end of file +- 建议先在测试环境中运行,确认无误后再部署到生产环境 diff --git a/docs/installation_cute.md b/docs/installation_cute.md index 4465660f9..e0c03310f 100644 --- a/docs/installation_cute.md +++ b/docs/installation_cute.md @@ -1,8 +1,9 @@ # 🔧 配置指南 喵~ -## 👋 你好呀! +## 👋 你好呀 让咱来告诉你我们要做什么喵: + 1. 我们要一起设置一个可爱的AI机器人 2. 这个机器人可以在QQ上陪你聊天玩耍哦 3. 需要设置两个文件才能让机器人工作呢 @@ -10,16 +11,19 @@ ## 📝 需要设置的文件喵 要设置这两个文件才能让机器人跑起来哦: + 1. `.env.prod` - 这个文件告诉机器人要用哪些AI服务呢 2. `bot_config.toml` - 这个文件教机器人怎么和你聊天喵 ## 🔑 密钥和域名的对应关系 想象一下,你要进入一个游乐园,需要: + 1. 知道游乐园的地址(这就是域名 base_url) 2. 有入场的门票(这就是密钥 key) 在 `.env.prod` 文件里,我们定义了三个游乐园的地址和门票喵: + ```ini # 硅基流动游乐园 SILICONFLOW_KEY=your_key # 硅基流动的门票 @@ -35,6 +39,7 @@ CHAT_ANY_WHERE_BASE_URL=https://api.chatanywhere.tech/v1 # ChatAnyWhere的地 ``` 然后在 `bot_config.toml` 里,机器人会用这些门票和地址去游乐园玩耍: + ```toml [model.llm_reasoning] name = "Pro/deepseek-ai/DeepSeek-R1" @@ -47,9 +52,10 @@ base_url = "SILICONFLOW_BASE_URL" # 还是去硅基流动游乐园 key = "SILICONFLOW_KEY" # 用同一张门票就可以啦 ``` -### 🎪 举个例子喵: +### 🎪 举个例子喵 如果你想用DeepSeek官方的服务,就要这样改: + ```toml [model.llm_reasoning] name = "deepseek-reasoner" # 改成对应的模型名称,这里为DeepseekR1 @@ -62,7 +68,8 @@ base_url = "DEEP_SEEK_BASE_URL" # 也去DeepSeek游乐园 key = "DEEP_SEEK_KEY" # 用同一张DeepSeek门票 ``` -### 🎯 简单来说: +### 🎯 简单来说 + - `.env.prod` 文件就像是你的票夹,存放着各个游乐园的门票和地址 - `bot_config.toml` 就是告诉机器人:用哪张票去哪个游乐园玩 - 所有模型都可以用同一个游乐园的票,也可以去不同的游乐园玩耍 @@ -88,19 +95,25 @@ CHAT_ANY_WHERE_KEY=your_key CHAT_ANY_WHERE_BASE_URL=https://api.chatanywhere.tech/v1 # 如果你不知道这是什么,那么下面这些不用改,保持原样就好啦 -HOST=127.0.0.1 # 如果使用Docker部署,需要改成0.0.0.0喵,不然听不见群友讲话了喵 +# 如果使用Docker部署,需要改成0.0.0.0喵,不然听不见群友讲话了喵 +HOST=127.0.0.1 PORT=8080 # 这些是数据库设置,一般也不用改呢 -MONGODB_HOST=127.0.0.1 # 如果使用Docker部署,需要改成数据库容器的名字喵,默认是mongodb喵 +# 如果使用Docker部署,需要把MONGODB_HOST改成数据库容器的名字喵,默认是mongodb喵 +MONGODB_HOST=127.0.0.1 MONGODB_PORT=27017 DATABASE_NAME=MegBot -MONGODB_USERNAME = "" # 如果数据库需要用户名,就在这里填写喵 -MONGODB_PASSWORD = "" # 如果数据库需要密码,就在这里填写呢 -MONGODB_AUTH_SOURCE = "" # 数据库认证源,一般不用改哦 +# 数据库认证信息,如果需要认证就取消注释并填写下面三行喵 +# MONGODB_USERNAME = "" +# MONGODB_PASSWORD = "" +# MONGODB_AUTH_SOURCE = "" -# 插件设置喵 -PLUGINS=["src2.plugins.chat"] # 这里是机器人的插件列表呢 +# 也可以使用URI连接数据库,取消注释填写在下面这行喵(URI的优先级比上面的高) +# MONGODB_URI=mongodb://127.0.0.1:27017/MegBot + +# 这里是机器人的插件列表呢 +PLUGINS=["src2.plugins.chat"] ``` ### 第二个文件:机器人配置 (bot_config.toml) @@ -199,10 +212,12 @@ key = "SILICONFLOW_KEY" - `topic`: 负责理解对话主题的能力呢 ## 🌟 小提示 + - 如果你刚开始使用,建议保持默认配置呢 - 不同的模型有不同的特长,可以根据需要调整它们的使用比例哦 ## 🌟 小贴士喵 + - 记得要好好保管密钥(key)哦,不要告诉别人呢 - 配置文件要小心修改,改错了机器人可能就不能和你玩了喵 - 如果想让机器人更聪明,可以调整 personality 里的设置呢 @@ -210,7 +225,8 @@ key = "SILICONFLOW_KEY" - QQ群号和QQ号都要用数字填写,不要加引号哦(除了机器人自己的QQ号) ## ⚠️ 注意事项 + - 这个机器人还在测试中呢,可能会有一些小问题喵 - 如果不知道怎么改某个设置,就保持原样不要动它哦~ - 记得要先有AI服务的密钥,不然机器人就不能和你说话了呢 -- 修改完配置后要重启机器人才能生效喵~ \ No newline at end of file +- 修改完配置后要重启机器人才能生效喵~ diff --git a/docs/installation_standard.md b/docs/installation_standard.md index 03b66dc46..dfaf0e797 100644 --- a/docs/installation_standard.md +++ b/docs/installation_standard.md @@ -3,6 +3,7 @@ ## 简介 本项目需要配置两个主要文件: + 1. `.env.prod` - 配置API服务和系统环境 2. `bot_config.toml` - 配置机器人行为和模型 @@ -10,7 +11,8 @@ `.env.prod` 和 `bot_config.toml` 中的API配置关系如下: -### 在.env.prod中定义API凭证: +### 在.env.prod中定义API凭证 + ```ini # API凭证配置 SILICONFLOW_KEY=your_key # 硅基流动API密钥 @@ -23,7 +25,8 @@ CHAT_ANY_WHERE_KEY=your_key # ChatAnyWhere API密钥 CHAT_ANY_WHERE_BASE_URL=https://api.chatanywhere.tech/v1 # ChatAnyWhere API地址 ``` -### 在bot_config.toml中引用API凭证: +### 在bot_config.toml中引用API凭证 + ```toml [model.llm_reasoning] name = "Pro/deepseek-ai/DeepSeek-R1" @@ -32,6 +35,7 @@ key = "SILICONFLOW_KEY" # 引用.env.prod中定义的密钥 ``` 如需切换到其他API服务,只需修改引用: + ```toml [model.llm_reasoning] name = "deepseek-reasoner" # 改成对应的模型名称,这里为DeepseekR1 @@ -42,6 +46,7 @@ key = "DEEP_SEEK_KEY" # 使用DeepSeek密钥 ## 配置文件详解 ### 环境配置文件 (.env.prod) + ```ini # API配置 SILICONFLOW_KEY=your_key @@ -52,22 +57,29 @@ CHAT_ANY_WHERE_KEY=your_key CHAT_ANY_WHERE_BASE_URL=https://api.chatanywhere.tech/v1 # 服务配置 + HOST=127.0.0.1 # 如果使用Docker部署,需要改成0.0.0.0,否则QQ消息无法传入 PORT=8080 # 与反向端口相同 # 数据库配置 MONGODB_HOST=127.0.0.1 # 如果使用Docker部署,需要改成数据库容器的名字,默认是mongodb MONGODB_PORT=27017 # MongoDB端口 + DATABASE_NAME=MegBot -MONGODB_USERNAME = "" # 数据库用户名 -MONGODB_PASSWORD = "" # 数据库密码 -MONGODB_AUTH_SOURCE = "" # 认证数据库 +# 数据库认证信息,如果需要认证就取消注释并填写下面三行 +# MONGODB_USERNAME = "" +# MONGODB_PASSWORD = "" +# MONGODB_AUTH_SOURCE = "" + +# 也可以使用URI连接数据库,取消注释填写在下面这行(URI的优先级比上面的高) +# MONGODB_URI=mongodb://127.0.0.1:27017/MegBot # 插件配置 PLUGINS=["src2.plugins.chat"] ``` ### 机器人配置文件 (bot_config.toml) + ```toml [bot] qq = "机器人QQ号" # 必填 @@ -154,4 +166,4 @@ key = "SILICONFLOW_KEY" 3. 其他说明: - 项目处于测试阶段,可能存在未知问题 - - 建议初次使用保持默认配置 \ No newline at end of file + - 建议初次使用保持默认配置 diff --git a/docs/manual_deploy_linux.md b/docs/manual_deploy_linux.md index 41f0390b8..4711c81a9 100644 --- a/docs/manual_deploy_linux.md +++ b/docs/manual_deploy_linux.md @@ -1,6 +1,7 @@ # 📦 Linux系统如何手动部署MaiMbot麦麦? ## 准备工作 + - 一台联网的Linux设备(本教程以Ubuntu/Debian系为例) - QQ小号(QQ框架的使用可能导致qq被风控,严重(小概率)可能会导致账号封禁,强烈不推荐使用大号) - 可用的大模型API @@ -20,6 +21,7 @@ - 数据库是什么?如何安装并启动MongoDB - 如何运行一个QQ机器人,以及NapCat框架是什么 + --- ## 环境配置 @@ -33,7 +35,9 @@ python --version # 或 python3 --version ``` + 如果版本低于3.9,请更新Python版本。 + ```bash # Ubuntu/Debian sudo apt update @@ -45,6 +49,7 @@ sudo update-alternatives --config python3 ``` ### 2️⃣ **创建虚拟环境** + ```bash # 方法1:使用venv(推荐) python3 -m venv maimbot @@ -65,13 +70,16 @@ pip install -r requirements.txt --- ## 数据库配置 -### 3️⃣ **安装并启动MongoDB** -- 安装与启动: Debian参考[官方文档](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-debian/),Ubuntu参考[官方文档](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/) +### 3️⃣ **安装并启动MongoDB** + +- 安装与启动:Debian参考[官方文档](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-debian/),Ubuntu参考[官方文档](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/) - 默认连接本地27017端口 + --- ## NapCat配置 + ### 4️⃣ **安装NapCat框架** - 参考[NapCat官方文档](https://www.napcat.wiki/guide/boot/Shell#napcat-installer-linux%E4%B8%80%E9%94%AE%E4%BD%BF%E7%94%A8%E8%84%9A%E6%9C%AC-%E6%94%AF%E6%8C%81ubuntu-20-debian-10-centos9)安装 @@ -81,15 +89,18 @@ pip install -r requirements.txt --- ## 配置文件设置 -### 5️⃣ **配置文件设置,让麦麦Bot正常工作** -- 修改环境配置文件: `.env.prod` -- 修改机器人配置文件: `bot_config.toml` +### 5️⃣ **配置文件设置,让麦麦Bot正常工作** + +- 修改环境配置文件:`.env.prod` +- 修改机器人配置文件:`bot_config.toml` --- ## 启动机器人 + ### 6️⃣ **启动麦麦机器人** + ```bash # 在项目目录下操作 nb run @@ -100,16 +111,18 @@ python3 bot.py --- ## **其他组件(可选)** -- 直接运行 knowledge.py生成知识库 +- 直接运行 knowledge.py生成知识库 --- ## 常见问题 -🔧 权限问题: 在命令前加 `sudo` -🔌 端口占用: 使用 `sudo lsof -i :8080` 查看端口占用 -🛡️ 防火墙: 确保8080/27017端口开放 + +🔧 权限问题:在命令前加`sudo` +🔌 端口占用:使用`sudo lsof -i :8080`查看端口占用 +🛡️ 防火墙:确保8080/27017端口开放 + ```bash sudo ufw allow 8080/tcp sudo ufw allow 27017/tcp -``` \ No newline at end of file +``` diff --git a/docs/manual_deploy_windows.md b/docs/manual_deploy_windows.md index eebdc4f41..37f0a5e31 100644 --- a/docs/manual_deploy_windows.md +++ b/docs/manual_deploy_windows.md @@ -30,12 +30,13 @@ 在创建虚拟环境之前,请确保你的电脑上安装了Python 3.9及以上版本。如果没有,可以按以下步骤安装: -1. 访问Python官网下载页面: https://www.python.org/downloads/release/python-3913/ +1. 访问Python官网下载页面: 2. 下载Windows安装程序 (64-bit): `python-3.9.13-amd64.exe` 3. 运行安装程序,并确保勾选"Add Python 3.9 to PATH"选项 4. 点击"Install Now"开始安装 或者使用PowerShell自动下载安装(需要管理员权限): + ```powershell # 下载并安装Python 3.9.13 $pythonUrl = "https://www.python.org/ftp/python/3.9.13/python-3.9.13-amd64.exe" @@ -46,7 +47,7 @@ Start-Process -Wait -FilePath $pythonInstaller -ArgumentList "/quiet", "InstallA ### 2️⃣ **创建Python虚拟环境来运行程序** - 你可以选择使用以下两种方法之一来创建Python环境: +> 你可以选择使用以下两种方法之一来创建Python环境: ```bash # ---方法1:使用venv(Python自带) @@ -60,6 +61,7 @@ maimbot\\Scripts\\activate # 安装依赖 pip install -r requirements.txt ``` + ```bash # ---方法2:使用conda # 创建一个新的conda环境(环境名为maimbot) @@ -74,27 +76,35 @@ pip install -r requirements.txt ``` ### 2️⃣ **然后你需要启动MongoDB数据库,来存储信息** + - 安装并启动MongoDB服务 - 默认连接本地27017端口 ### 3️⃣ **配置NapCat,让麦麦bot与qq取得联系** + - 安装并登录NapCat(用你的qq小号) - 添加反向WS: `ws://127.0.0.1:8080/onebot/v11/ws` ### 4️⃣ **配置文件设置,让麦麦Bot正常工作** -- 修改环境配置文件: `.env.prod` -- 修改机器人配置文件: `bot_config.toml` + +- 修改环境配置文件:`.env.prod` +- 修改机器人配置文件:`bot_config.toml` ### 5️⃣ **启动麦麦机器人** + - 打开命令行,cd到对应路径 + ```bash nb run ``` + - 或者cd到对应路径后 + ```bash python bot.py ``` ### 6️⃣ **其他组件(可选)** + - `run_thingking.bat`: 启动可视化推理界面(未完善) - 直接运行 knowledge.py生成知识库 diff --git a/src/common/database.py b/src/common/database.py index 45ac05dac..f0954b07c 100644 --- a/src/common/database.py +++ b/src/common/database.py @@ -6,20 +6,44 @@ from pymongo import MongoClient class Database: _instance: Optional["Database"] = None - def __init__(self, host: str, port: int, db_name: str, username: Optional[str] = None, password: Optional[str] = None, auth_source: Optional[str] = None): - if username and password: + def __init__( + self, + host: str, + port: int, + db_name: str, + username: Optional[str] = None, + password: Optional[str] = None, + auth_source: Optional[str] = None, + uri: Optional[str] = None, + ): + if uri and uri.startswith("mongodb://"): + # 优先使用URI连接 + self.client = MongoClient(uri) + elif username and password: # 如果有用户名和密码,使用认证连接 - # TODO: 复杂情况直接支持URI吧 - self.client = MongoClient(host, port, username=username, password=password, authSource=auth_source) + self.client = MongoClient( + host, port, username=username, password=password, authSource=auth_source + ) else: # 否则使用无认证连接 self.client = MongoClient(host, port) self.db = self.client[db_name] @classmethod - def initialize(cls, host: str, port: int, db_name: str, username: Optional[str] = None, password: Optional[str] = None, auth_source: Optional[str] = None) -> "Database": + def initialize( + cls, + host: str, + port: int, + db_name: str, + username: Optional[str] = None, + password: Optional[str] = None, + auth_source: Optional[str] = None, + uri: Optional[str] = None, + ) -> "Database": if cls._instance is None: - cls._instance = cls(host, port, db_name, username, password, auth_source) + cls._instance = cls( + host, port, db_name, username, password, auth_source, uri + ) return cls._instance @classmethod diff --git a/src/gui/reasoning_gui.py b/src/gui/reasoning_gui.py index 5768ddc09..e131658b8 100644 --- a/src/gui/reasoning_gui.py +++ b/src/gui/reasoning_gui.py @@ -7,7 +7,7 @@ from datetime import datetime from typing import Dict, List from loguru import logger from typing import Optional -from pymongo import MongoClient +from ..common.database import Database import customtkinter as ctk from dotenv import load_dotenv @@ -28,38 +28,6 @@ else: logger.error("未找到环境配置文件") sys.exit(1) - -class Database: - _instance: Optional["Database"] = None - - def __init__(self, host: str, port: int, db_name: str, username: str = None, password: str = None, - auth_source: str = None): - if username and password: - self.client = MongoClient( - host=host, - port=port, - username=username, - password=password, - authSource=auth_source or 'admin' - ) - else: - self.client = MongoClient(host, port) - self.db = self.client[db_name] - - @classmethod - def initialize(cls, host: str, port: int, db_name: str, username: str = None, password: str = None, - auth_source: str = None) -> "Database": - if cls._instance is None: - cls._instance = cls(host, port, db_name, username, password, auth_source) - return cls._instance - - @classmethod - def get_instance(cls) -> "Database": - if cls._instance is None: - raise RuntimeError("Database not initialized") - return cls._instance - - class ReasoningGUI: def __init__(self): # 记录启动时间戳,转换为Unix时间戳 @@ -83,7 +51,15 @@ class ReasoningGUI: except RuntimeError: logger.warning("数据库未初始化,正在尝试初始化...") try: - Database.initialize("127.0.0.1", 27017, "maimai_bot") + Database.initialize( + uri=os.getenv("MONGODB_URI"), + host=os.getenv("MONGODB_HOST", "127.0.0.1"), + port=int(os.getenv("MONGODB_PORT", "27017")), + db_name=os.getenv("DATABASE_NAME", "MegBot"), + username=os.getenv("MONGODB_USERNAME"), + password=os.getenv("MONGODB_PASSWORD"), + auth_source=os.getenv("MONGODB_AUTH_SOURCE"), + ) self.db = Database.get_instance().db logger.success("数据库初始化成功") except Exception: @@ -359,12 +335,13 @@ class ReasoningGUI: def main(): """主函数""" Database.initialize( - host=os.getenv("MONGODB_HOST"), - port=int(os.getenv("MONGODB_PORT")), - db_name=os.getenv("DATABASE_NAME"), + uri=os.getenv("MONGODB_URI"), + host=os.getenv("MONGODB_HOST", "127.0.0.1"), + port=int(os.getenv("MONGODB_PORT", "27017")), + db_name=os.getenv("DATABASE_NAME", "MegBot"), username=os.getenv("MONGODB_USERNAME"), password=os.getenv("MONGODB_PASSWORD"), - auth_source=os.getenv("MONGODB_AUTH_SOURCE") + auth_source=os.getenv("MONGODB_AUTH_SOURCE"), ) app = ReasoningGUI() diff --git a/src/plugins/chat/__init__.py b/src/plugins/chat/__init__.py index c730466b3..2e01262b1 100644 --- a/src/plugins/chat/__init__.py +++ b/src/plugins/chat/__init__.py @@ -31,6 +31,7 @@ driver = get_driver() config = driver.config Database.initialize( + uri=config.MONGODB_URI, host=config.MONGODB_HOST, port=int(config.MONGODB_PORT), db_name=config.DATABASE_NAME, diff --git a/src/plugins/chat/utils_image.py b/src/plugins/chat/utils_image.py index 8a8b3ce5a..7e57560c9 100644 --- a/src/plugins/chat/utils_image.py +++ b/src/plugins/chat/utils_image.py @@ -37,14 +37,7 @@ def storage_compress_image(base64_data: str, max_size: int = 200) -> str: os.makedirs(images_dir, exist_ok=True) # 连接数据库 - db = Database( - host=config.mongodb_host, - port=int(config.mongodb_port), - db_name=config.database_name, - username=config.mongodb_username, - password=config.mongodb_password, - auth_source=config.mongodb_auth_source - ) + db = Database.get_instance() # 检查是否已存在相同哈希值的图片 collection = db.db['images'] diff --git a/src/plugins/knowledege/knowledge_library.py b/src/plugins/knowledege/knowledge_library.py index 4bf6227bb..e9d7167fd 100644 --- a/src/plugins/knowledege/knowledge_library.py +++ b/src/plugins/knowledege/knowledge_library.py @@ -19,12 +19,13 @@ from src.common.database import Database # 从环境变量获取配置 Database.initialize( + uri=os.getenv("MONGODB_URI"), host=os.getenv("MONGODB_HOST", "127.0.0.1"), port=int(os.getenv("MONGODB_PORT", "27017")), - db_name=os.getenv("DATABASE_NAME", "maimai"), + db_name=os.getenv("DATABASE_NAME", "MegBot"), username=os.getenv("MONGODB_USERNAME"), password=os.getenv("MONGODB_PASSWORD"), - auth_source=os.getenv("MONGODB_AUTH_SOURCE", "admin") + auth_source=os.getenv("MONGODB_AUTH_SOURCE"), ) class KnowledgeLibrary: diff --git a/src/plugins/memory_system/draw_memory.py b/src/plugins/memory_system/draw_memory.py index 6da330d95..9f15164f1 100644 --- a/src/plugins/memory_system/draw_memory.py +++ b/src/plugins/memory_system/draw_memory.py @@ -9,7 +9,10 @@ import networkx as nx from dotenv import load_dotenv from loguru import logger -sys.path.append("C:/GitHub/MaiMBot") # 添加项目根目录到 Python 路径 +# 添加项目根目录到 Python 路径 +root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../..")) +sys.path.append(root_path) + from src.common.database import Database # 使用正确的导入语法 # 加载.env.dev文件 @@ -162,12 +165,13 @@ class Memory_graph: def main(): # 初始化数据库 Database.initialize( + uri=os.getenv("MONGODB_URI"), host=os.getenv("MONGODB_HOST", "127.0.0.1"), port=int(os.getenv("MONGODB_PORT", "27017")), db_name=os.getenv("DATABASE_NAME", "MegBot"), - username=os.getenv("MONGODB_USERNAME", ""), - password=os.getenv("MONGODB_PASSWORD", ""), - auth_source=os.getenv("MONGODB_AUTH_SOURCE", "") + username=os.getenv("MONGODB_USERNAME"), + password=os.getenv("MONGODB_PASSWORD"), + auth_source=os.getenv("MONGODB_AUTH_SOURCE"), ) memory_graph = Memory_graph() diff --git a/src/plugins/memory_system/memory.py b/src/plugins/memory_system/memory.py index e7198b10e..13a9f8c38 100644 --- a/src/plugins/memory_system/memory.py +++ b/src/plugins/memory_system/memory.py @@ -8,6 +8,7 @@ import jieba import networkx as nx from loguru import logger +from nonebot import get_driver from ...common.database import Database # 使用正确的导入语法 from ..chat.config import global_config from ..chat.utils import ( @@ -18,7 +19,6 @@ from ..chat.utils import ( ) from ..models.utils_model import LLM_request - class Memory_graph: def __init__(self): self.G = nx.Graph() # 使用 networkx 的图结构 @@ -150,7 +150,7 @@ class Memory_graph: return None -# 海马体 +# 海马体 class Hippocampus: def __init__(self, memory_graph: Memory_graph): self.memory_graph = memory_graph @@ -881,15 +881,13 @@ def segment_text(text): seg_text = list(jieba.cut(text)) return seg_text - -from nonebot import get_driver - driver = get_driver() config = driver.config start_time = time.time() Database.initialize( + uri=config.MONGODB_URI, host=config.MONGODB_HOST, port=config.MONGODB_PORT, db_name=config.DATABASE_NAME, diff --git a/src/plugins/memory_system/memory_manual_build.py b/src/plugins/memory_system/memory_manual_build.py index 3c120f21b..9c1d43ce9 100644 --- a/src/plugins/memory_system/memory_manual_build.py +++ b/src/plugins/memory_system/memory_manual_build.py @@ -16,7 +16,10 @@ from loguru import logger import jieba # from chat.config import global_config -sys.path.append("C:/GitHub/MaiMBot") # 添加项目根目录到 Python 路径 +# 添加项目根目录到 Python 路径 +root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../..")) +sys.path.append(root_path) + from src.common.database import Database from src.plugins.memory_system.offline_llm import LLMModel @@ -35,45 +38,6 @@ else: logger.warning(f"未找到环境变量文件: {env_path}") logger.info("将使用默认配置") -class Database: - _instance = None - db = None - - @classmethod - def get_instance(cls): - if cls._instance is None: - cls._instance = cls() - return cls._instance - - def __init__(self): - if not Database.db: - Database.initialize( - host=os.getenv("MONGODB_HOST"), - port=int(os.getenv("MONGODB_PORT")), - db_name=os.getenv("DATABASE_NAME"), - username=os.getenv("MONGODB_USERNAME"), - password=os.getenv("MONGODB_PASSWORD"), - auth_source=os.getenv("MONGODB_AUTH_SOURCE") - ) - - @classmethod - def initialize(cls, host, port, db_name, username=None, password=None, auth_source="admin"): - try: - if username and password: - uri = f"mongodb://{username}:{password}@{host}:{port}/{db_name}?authSource={auth_source}" - else: - uri = f"mongodb://{host}:{port}" - - client = pymongo.MongoClient(uri) - cls.db = client[db_name] - # 测试连接 - client.server_info() - logger.success("MongoDB连接成功!") - - except Exception as e: - logger.error(f"初始化MongoDB失败: {str(e)}") - raise - def calculate_information_content(text): """计算文本的信息量(熵)""" char_count = Counter(text) @@ -202,7 +166,7 @@ class Memory_graph: # 返回所有节点对应的 Memory_dot 对象 return [self.get_dot(node) for node in self.G.nodes()] -# 海马体 +# 海马体 class Hippocampus: def __init__(self, memory_graph: Memory_graph): self.memory_graph = memory_graph @@ -941,59 +905,67 @@ def visualize_graph_lite(memory_graph: Memory_graph, color_by_memory: bool = Fal async def main(): # 初始化数据库 logger.info("正在初始化数据库连接...") - db = Database.get_instance() + Database.initialize( + uri=os.getenv("MONGODB_URI"), + host=os.getenv("MONGODB_HOST", "127.0.0.1"), + port=int(os.getenv("MONGODB_PORT", "27017")), + db_name=os.getenv("DATABASE_NAME", "MegBot"), + username=os.getenv("MONGODB_USERNAME"), + password=os.getenv("MONGODB_PASSWORD"), + auth_source=os.getenv("MONGODB_AUTH_SOURCE"), + ) start_time = time.time() - + test_pare = {'do_build_memory':False,'do_forget_topic':False,'do_visualize_graph':True,'do_query':False,'do_merge_memory':False} - + # 创建记忆图 memory_graph = Memory_graph() - + # 创建海马体 hippocampus = Hippocampus(memory_graph) - + # 从数据库同步数据 hippocampus.sync_memory_from_db() - + end_time = time.time() logger.info(f"\033[32m[加载海马体耗时: {end_time - start_time:.2f} 秒]\033[0m") - + # 构建记忆 if test_pare['do_build_memory']: logger.info("开始构建记忆...") chat_size = 20 await hippocampus.operation_build_memory(chat_size=chat_size) - + end_time = time.time() logger.info(f"\033[32m[构建记忆耗时: {end_time - start_time:.2f} 秒,chat_size={chat_size},chat_count = 16]\033[0m") - + if test_pare['do_forget_topic']: logger.info("开始遗忘记忆...") await hippocampus.operation_forget_topic(percentage=0.1) - + end_time = time.time() logger.info(f"\033[32m[遗忘记忆耗时: {end_time - start_time:.2f} 秒]\033[0m") - + if test_pare['do_merge_memory']: logger.info("开始合并记忆...") await hippocampus.operation_merge_memory(percentage=0.1) - + end_time = time.time() logger.info(f"\033[32m[合并记忆耗时: {end_time - start_time:.2f} 秒]\033[0m") - + if test_pare['do_visualize_graph']: # 展示优化后的图形 logger.info("生成记忆图谱可视化...") print("\n生成优化后的记忆图谱:") visualize_graph_lite(memory_graph) - + if test_pare['do_query']: # 交互式查询 while True: query = input("\n请输入新的查询概念(输入'退出'以结束):") if query.lower() == '退出': break - + items_list = memory_graph.get_related_item(query) if items_list: first_layer, second_layer = items_list @@ -1008,9 +980,6 @@ async def main(): else: print("未找到相关记忆。") - if __name__ == "__main__": import asyncio asyncio.run(main()) - - diff --git a/src/plugins/schedule/schedule_generator.py b/src/plugins/schedule/schedule_generator.py index e280c6bce..2fe259c47 100644 --- a/src/plugins/schedule/schedule_generator.py +++ b/src/plugins/schedule/schedule_generator.py @@ -14,6 +14,7 @@ driver = get_driver() config = driver.config Database.initialize( + uri=config.MONGODB_URI, host=config.MONGODB_HOST, port=int(config.MONGODB_PORT), db_name=config.DATABASE_NAME, @@ -22,7 +23,6 @@ Database.initialize( auth_source=config.MONGODB_AUTH_SOURCE ) - class ScheduleGenerator: def __init__(self): # 根据global_config.llm_normal这一字典配置指定模型 diff --git a/template.env b/template.env index 09fe63597..d2a763112 100644 --- a/template.env +++ b/template.env @@ -5,13 +5,18 @@ PORT=8080 PLUGINS=["src2.plugins.chat"] # 默认配置 -MONGODB_HOST=127.0.0.1 # 如果工作在Docker下,请改成 MONGODB_HOST=mongodb +# 如果工作在Docker下,请改成 MONGODB_HOST=mongodb +MONGODB_HOST=127.0.0.1 MONGODB_PORT=27017 DATABASE_NAME=MegBot -MONGODB_USERNAME = "" # 默认空值 -MONGODB_PASSWORD = "" # 默认空值 -MONGODB_AUTH_SOURCE = "" # 默认空值 +# 也可以使用 URI 连接数据库(优先级比上面的高) +# MONGODB_URI=mongodb://127.0.0.1:27017/MegBot + +# MongoDB 认证信息,若需要认证,请取消注释以下三行并填写正确的信息 +# MONGODB_USERNAME=user +# MONGODB_PASSWORD=password +# MONGODB_AUTH_SOURCE=admin #key and url CHAT_ANY_WHERE_BASE_URL=https://api.chatanywhere.tech/v1 @@ -21,4 +26,4 @@ DEEP_SEEK_BASE_URL=https://api.deepseek.com/v1 #定义你要用的api的base_url DEEP_SEEK_KEY= CHAT_ANY_WHERE_KEY= -SILICONFLOW_KEY= \ No newline at end of file +SILICONFLOW_KEY=