From d9327d47fc8d715e55fbb14f1e4a38e7865f3b4d Mon Sep 17 00:00:00 2001
From: SengokuCola <1026294844@qq.com>
Date: Sat, 1 Mar 2025 12:55:02 +0800
Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E8=AF=B4=E6=98=8E?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
123
---
README.md | 95 ++++++++++++++++++++
requirements.txt | Bin 1088 -> 908 bytes
src/gui/reasoning_gui.py | 142 +++++++++++++++---------------
src/plugins/chat/bot_config_toml | 4 +-
src/plugins/chat/llm_generator.py | 2 +-
5 files changed, 170 insertions(+), 73 deletions(-)
diff --git a/README.md b/README.md
index 972dbfca9..3e2da652a 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,15 @@
关于麦麦的开发和部署相关的讨论群(不建议发布无关消息)这里不会有麦麦发言!
+## 开发计划TODO:LIST
+
+- 兼容gif的解析和保存
+- 小程序转发链接解析
+- 对思考链长度限制
+- 修复已知bug
+- 完善文档
+
+
@@ -62,6 +71,92 @@ NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker compose restart
- 把env.example改成.env,并填上你的apikey(硅基流动或deepseekapi)
- 把bot_config_toml改名为bot_config.toml,并填写相关内容,不然无法正常运行
+ #### .env 文件配置说明
+ ```ini
+ # 环境配置
+ ENVIRONMENT=dev # 开发环境设置
+ HOST=127.0.0.1 # 主机地址
+ PORT=8080 # 端口号
+
+ # 命令前缀设置
+ COMMAND_START=["/"] # 命令起始符
+
+ # 插件配置
+ PLUGINS=["src2.plugins.chat"] # 启用的插件列表
+
+ # MongoDB配置
+ MONGODB_HOST=127.0.0.1 # MongoDB主机地址
+ MONGODB_PORT=27017 # MongoDB端口
+ DATABASE_NAME=MegBot # 数据库名称
+ MONGODB_USERNAME="" # MongoDB用户名(可选)
+ MONGODB_PASSWORD="" # MongoDB密码(可选)
+ MONGODB_AUTH_SOURCE="" # MongoDB认证源(可选)
+
+ # API密钥配置
+ CHAT_ANY_WHERE_KEY= # ChatAnyWhere API密钥
+ SILICONFLOW_KEY= # 硅基流动 API密钥(必填)
+ DEEP_SEEK_KEY= # DeepSeek API密钥(必填)
+
+ # API地址配置
+ CHAT_ANY_WHERE_BASE_URL=https://api.chatanywhere.tech/v1
+ SILICONFLOW_BASE_URL=https://api.siliconflow.cn/v1/
+ DEEP_SEEK_BASE_URL=https://api.deepseek.com/v1
+ ```
+
+ #### bot_config.toml 文件配置说明
+ ```toml
+ # 数据库设置
+ [database]
+ host = "127.0.0.1" # MongoDB主机地址
+ port = 27017 # MongoDB端口
+ name = "MegBot" # 数据库名称
+
+ # 机器人基本设置
+ [bot]
+ qq = # 你的机器人QQ号(必填)
+ nickname = "麦麦" # 机器人昵称
+
+ # 消息处理设置
+ [message]
+ min_text_length = 2 # 最小响应文本长度
+ max_context_size = 15 # 上下文最大保存数量
+ emoji_chance = 0.2 # 表情包使用概率
+
+ # 表情包功能设置
+ [emoji]
+ check_interval = 120 # 表情检查间隔(秒)
+ register_interval = 10 # 表情注册间隔(秒)
+
+ # CQ码设置
+ [cq_code]
+ enable_pic_translate = false # 是否启用图片转换(无效)
+
+ # 响应设置
+ [response]
+ api_using = "siliconflow" # 回复使用的API(siliconflow/deepseek)
+ model_r1_probability = 0.8 # R1模型使用概率
+ model_v3_probability = 0.1 # V3模型使用概率
+ model_r1_distill_probability = 0.1 # R1蒸馏模型使用概率(对deepseek api 无效)
+
+ # 其他设置
+ [others]
+ enable_advance_output = false # 是否启用详细日志输出
+
+ # 群组设置
+ [groups]
+ talk_allowed = [ # 允许回复的群号列表
+ # 在这里添加群号,逗号隔开
+ ]
+
+ talk_frequency_down = [ # 降低回复频率的群号列表
+ # 在这里添加群号,逗号隔开
+ ]
+
+ ban_user_id = [ # 禁止回复的用户QQ号列表
+ # 在这里添加QQ号,逗号隔开
+ ]
+ ```
+
5. **运行麦麦**
```bash
conda activate 你的环境
diff --git a/requirements.txt b/requirements.txt
index d94f30ecda2ab4d5088ad57c1a072d29f1e2b66a..7ddb691bcc431d9881ceedcd914bf094e10dc2be 100644
GIT binary patch
delta 81
zcmX@W(ZfFB&tx7(jmbWYa+BK_6(+A@l+)s6;9@9ZNM$HwC$3Xm>{Jj^PPyTJCZVw}eXa@5n<^1#V)lU=TCgi@{(;YRqW>E{ZTw
diff --git a/src/gui/reasoning_gui.py b/src/gui/reasoning_gui.py
index 79e274d6d..356be3bd1 100644
--- a/src/gui/reasoning_gui.py
+++ b/src/gui/reasoning_gui.py
@@ -73,7 +73,7 @@ class ReasoningGUI:
self.frame.pack(pady=20, padx=20, fill="both", expand=True)
# 添加标题
- self.title = ctk.CTkLabel(self.frame, text="AI推理监控系统", font=("Arial", 24))
+ self.title = ctk.CTkLabel(self.frame, text="麦麦的脑内所想", font=("Arial", 24))
self.title.pack(pady=10, padx=10)
# 创建左右分栏
@@ -87,8 +87,14 @@ class ReasoningGUI:
self.group_label = ctk.CTkLabel(self.left_frame, text="群组列表", font=("Arial", 16))
self.group_label.pack(pady=5)
- self.group_listbox = ctk.CTkTextbox(self.left_frame, width=180, height=400)
- self.group_listbox.pack(pady=5, padx=5)
+ # 创建可滚动框架来容纳群组按钮
+ self.group_scroll_frame = ctk.CTkScrollableFrame(self.left_frame, width=180, height=400)
+ self.group_scroll_frame.pack(pady=5, padx=5, fill="both", expand=True)
+
+ # 存储群组按钮的字典
+ self.group_buttons: Dict[str, ctk.CTkButton] = {}
+ # 当前选中的群组ID
+ self.selected_group_id: Optional[str] = None
# 右侧内容显示
self.right_frame = ctk.CTkFrame(self.paned)
@@ -106,6 +112,7 @@ class ReasoningGUI:
self.content_text.tag_config("user", foreground="#4CAF50") # 用户名使用绿色
self.content_text.tag_config("message", foreground="#2196F3") # 消息使用蓝色
self.content_text.tag_config("model", foreground="#9C27B0") # 模型名称使用紫色
+ self.content_text.tag_config("prompt", foreground="#FF9800") # prompt内容使用橙色
self.content_text.tag_config("reasoning", foreground="#FF9800") # 推理过程使用橙色
self.content_text.tag_config("response", foreground="#E91E63") # 回复使用粉色
self.content_text.tag_config("separator", foreground="#666666") # 分隔符使用深灰色
@@ -122,9 +129,6 @@ class ReasoningGUI:
)
self.clear_button.pack(side="left", padx=5)
- # 添加群组点击事件
- self.group_listbox.bind('', self._on_group_click)
-
# 启动自动更新线程
self.update_thread = threading.Thread(target=self._auto_update, daemon=True)
self.update_thread.start()
@@ -154,9 +158,45 @@ class ReasoningGUI:
def _update_group_list_gui(self):
"""在主线程中更新群组列表"""
- self.group_listbox.delete("1.0", "end")
+ # 清除现有按钮
+ for button in self.group_buttons.values():
+ button.destroy()
+ self.group_buttons.clear()
+
+ # 创建新的群组按钮
for group_id in self.group_data.keys():
- self.group_listbox.insert("end", f"群号: {group_id}\n")
+ button = ctk.CTkButton(
+ self.group_scroll_frame,
+ text=f"群号: {group_id}",
+ width=160,
+ height=30,
+ corner_radius=8,
+ command=lambda gid=group_id: self._on_group_select(gid)
+ )
+ button.pack(pady=2, padx=5)
+ self.group_buttons[group_id] = button
+
+ # 如果有选中的群组,保持其高亮状态
+ if self.selected_group_id and self.selected_group_id in self.group_buttons:
+ self._highlight_selected_group(self.selected_group_id)
+
+ def _on_group_select(self, group_id: str):
+ """处理群组选择事件"""
+ self._highlight_selected_group(group_id)
+ self._update_display_gui(group_id)
+
+ def _highlight_selected_group(self, group_id: str):
+ """高亮显示选中的群组按钮"""
+ # 重置所有按钮的颜色
+ for gid, button in self.group_buttons.items():
+ if gid == group_id:
+ # 设置选中按钮的颜色
+ button.configure(fg_color="#1E88E5", hover_color="#1976D2")
+ else:
+ # 恢复其他按钮的默认颜色
+ button.configure(fg_color="#2B2B2B", hover_color="#404040")
+
+ self.selected_group_id = group_id
def _update_display_gui(self, group_id: str):
"""在主线程中更新显示内容"""
@@ -179,15 +219,27 @@ class ReasoningGUI:
self.content_text.insert("end", "模型: ", "timestamp")
self.content_text.insert("end", f"{item.get('model', '')}\n", "model")
+ # Prompt内容
+ self.content_text.insert("end", "Prompt内容:\n", "timestamp")
+ prompt_text = item.get('prompt', '')
+ if prompt_text and prompt_text.lower() != 'none':
+ lines = prompt_text.split('\n')
+ for line in lines:
+ if line.strip():
+ self.content_text.insert("end", " " + line + "\n", "prompt")
+ else:
+ self.content_text.insert("end", " 无Prompt内容\n", "prompt")
+
# 推理过程
self.content_text.insert("end", "推理过程:\n", "timestamp")
reasoning_text = item.get('reasoning', '')
- # 处理推理过程中的Markdown格式
- lines = reasoning_text.split('\n')
- for line in lines:
- if line.strip():
- # 添加缩进
- self.content_text.insert("end", " " + line + "\n", "reasoning")
+ if reasoning_text and reasoning_text.lower() != 'none':
+ lines = reasoning_text.split('\n')
+ for line in lines:
+ if line.strip():
+ self.content_text.insert("end", " " + line + "\n", "reasoning")
+ else:
+ self.content_text.insert("end", " 无推理过程\n", "reasoning")
# 回复内容
self.content_text.insert("end", "回复: ", "timestamp")
@@ -237,11 +289,12 @@ class ReasoningGUI:
new_data[group_id].append({
'time': time_obj,
- 'user': item.get('user_nickname', item.get('user_id', '未知')),
+ 'user': item.get('user', '未知'),
'message': item.get('message', ''),
'model': item.get('model', '未知'),
'reasoning': item.get('reasoning', ''),
'response': item.get('response', ''),
+ 'prompt': item.get('prompt', '') # 添加prompt字段
})
print(f"从数据库加载了 {total_count} 条记录,分布在 {len(new_data)} 个群组中")
@@ -253,10 +306,12 @@ class ReasoningGUI:
# 将更新任务添加到队列
self.update_queue.put({'type': 'update_group_list'})
if self.group_data:
- latest_group = next(iter(self.group_data))
+ # 如果没有选中的群组,选择最新的群组
+ if not self.selected_group_id or self.selected_group_id not in self.group_data:
+ self.selected_group_id = next(iter(self.group_data))
self.update_queue.put({
'type': 'update_display',
- 'group_id': latest_group
+ 'group_id': self.selected_group_id
})
except Exception as e:
print(f"自动更新出错: {e}")
@@ -264,59 +319,6 @@ class ReasoningGUI:
# 每5秒更新一次
time.sleep(5)
- def _on_group_click(self, event):
- """处理群组点击事件"""
- try:
- # 获取点击位置的文本行
- index = self.group_listbox.index(f"@{event.x},{event.y}")
- line = self.group_listbox.get(f"{index} linestart", f"{index} lineend")
- if line.startswith("群号: "):
- group_id = line.replace("群号: ", "").strip()
- self.update_display(group_id)
- except Exception as e:
- print(f"处理群组点击事件出错: {e}")
-
- def update_display(self, group_id: str):
- """更新显示指定群组的内容"""
- if group_id in self.group_data:
- self.content_text.delete("1.0", "end")
- for item in self.group_data[group_id]:
- # 时间戳
- time_str = item['time'].strftime("%Y-%m-%d %H:%M:%S")
- self.content_text.insert("end", f"[{time_str}]\n", "timestamp")
-
- # 用户信息
- self.content_text.insert("end", "用户: ", "timestamp")
- self.content_text.insert("end", f"** {item.get('user', '未知')} **\n", "user")
-
- # 消息内容
- self.content_text.insert("end", "消息: ", "timestamp")
- self.content_text.insert("end", f"{item.get('message', '')}\n", "message")
-
- # 模型信息
- self.content_text.insert("end", "模型: ", "timestamp")
- self.content_text.insert("end", f"{item.get('model', '')}\n", "model")
-
- # 推理过程
- self.content_text.insert("end", "推理过程:\n", "timestamp")
- reasoning_text = item.get('reasoning', '')
- # 处理推理过程中的Markdown格式
- lines = reasoning_text.split('\n')
- for line in lines:
- if line.strip():
- # 添加缩进
- self.content_text.insert("end", " " + line + "\n", "reasoning")
-
- # 回复内容
- self.content_text.insert("end", "回复: ", "timestamp")
- self.content_text.insert("end", f"{item.get('response', '')}\n", "response")
-
- # 分隔符
- self.content_text.insert("end", f"\n{'='*50}\n\n", "separator")
-
- # 滚动到顶部
- self.content_text.see("1.0")
-
def clear_display(self):
"""清除显示内容"""
self.content_text.delete("1.0", "end")
diff --git a/src/plugins/chat/bot_config_toml b/src/plugins/chat/bot_config_toml
index f51a7a4d8..fe6b702d8 100644
--- a/src/plugins/chat/bot_config_toml
+++ b/src/plugins/chat/bot_config_toml
@@ -20,7 +20,7 @@ check_interval = 120
register_interval = 10
[cq_code]
-enable_pic_translate = true
+enable_pic_translate = false
[response]
@@ -30,7 +30,7 @@ model_v3_probability = 0.1 # 麦麦回答时选择V3模型的概率
model_r1_distill_probability = 0.1 # 麦麦回答时选择R1蒸馏模型的概率
[others]
-enable_advance_output = false # 开启后输出更多日志,false关闭true开启
+enable_advance_output = true # 开启后输出更多日志,false关闭true开启
[groups]
diff --git a/src/plugins/chat/llm_generator.py b/src/plugins/chat/llm_generator.py
index 98494d795..bb68d3618 100644
--- a/src/plugins/chat/llm_generator.py
+++ b/src/plugins/chat/llm_generator.py
@@ -129,7 +129,7 @@ class LLMResponseGenerator:
content = response.choices[0].message.content
# 获取推理内容
- reasoning_content = "模型思考过程:\n" + prompt
+ reasoning_content = ""
if hasattr(response.choices[0].message, "reasoning"):
reasoning_content = response.choices[0].message.reasoning or reasoning_content
elif hasattr(response.choices[0].message, "reasoning_content"):