插件化项目优化,支持将代码改造为插件,支持自动加载
This commit is contained in:
3
plugins/message_summary/__init__.py
Normal file
3
plugins/message_summary/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# 插件初始化文件
|
||||
# 从main模块导入插件类
|
||||
from .main import MessageSummaryPlugin
|
||||
12
plugins/message_summary/config.toml
Normal file
12
plugins/message_summary/config.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
# 消息总结插件配置
|
||||
|
||||
[general]
|
||||
enabled = true
|
||||
|
||||
[api]
|
||||
api_key = "app-McGLzBhBjeBCSEi7n83MtuTo"
|
||||
api_url = "http://192.168.2.240/v1/chat-messages"
|
||||
|
||||
[output]
|
||||
output_dir = "output"
|
||||
image_format = "png"
|
||||
192
plugins/message_summary/main.py
Normal file
192
plugins/message_summary/main.py
Normal file
@@ -0,0 +1,192 @@
|
||||
import os
|
||||
import time
|
||||
import requests
|
||||
import json
|
||||
from typing import Dict, Any, Tuple, Optional, List
|
||||
|
||||
from message_storage.message_to_db import MessageStorage
|
||||
from plugin_common.plugin_interface import PluginStatus
|
||||
from plugin_common.message_plugin_interface import MessagePluginInterface
|
||||
from message_summary.compress_chat_data import compress_chat_data
|
||||
from message_summary.markdown_to_image import convert_md_str_to_image
|
||||
|
||||
|
||||
class MessageSummaryPlugin(MessagePluginInterface):
|
||||
"""消息总结插件,用于生成群聊消息总结"""
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
return "message_summary"
|
||||
|
||||
@property
|
||||
def version(self) -> str:
|
||||
return "1.0.0"
|
||||
|
||||
@property
|
||||
def description(self) -> str:
|
||||
return "使用AI生成群聊消息总结"
|
||||
|
||||
@property
|
||||
def author(self) -> str:
|
||||
return "WeChatRobot Team"
|
||||
|
||||
@property
|
||||
def command_prefix(self) -> Optional[str]:
|
||||
return "#"
|
||||
|
||||
@property
|
||||
def commands(self) -> List[str]:
|
||||
return ["总结", "summary"]
|
||||
|
||||
def initialize(self, context: Dict[str, Any]) -> bool:
|
||||
"""初始化插件"""
|
||||
try:
|
||||
# 从插件配置中获取API密钥和URL
|
||||
api_config = self._config.get("api", {})
|
||||
self._api_key = api_config.get("api_key", "app-McGLzBhBjeBCSEi7n83MtuTo")
|
||||
self._api_url = api_config.get("api_url", "http://192.168.2.240/v1/chat-messages")
|
||||
|
||||
self.all_contacts = context["all_contacts"]
|
||||
self.message_storage = MessageStorage()
|
||||
|
||||
print(f"初始化 {self.name} 插件成功")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"初始化 {self.name} 插件失败: {e}")
|
||||
return False
|
||||
|
||||
def start(self) -> bool:
|
||||
"""启动插件"""
|
||||
self.status = PluginStatus.RUNNING
|
||||
print(f"{self.name} 插件已启动")
|
||||
return True
|
||||
|
||||
def stop(self) -> bool:
|
||||
"""停止插件"""
|
||||
self.status = PluginStatus.STOPPED
|
||||
print(f"{self.name} 插件已停止")
|
||||
return True
|
||||
|
||||
def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
|
||||
"""处理消息"""
|
||||
try:
|
||||
# 检查是否是总结命令
|
||||
content = message.get("content", "")
|
||||
if not content.startswith(self.command_prefix):
|
||||
return False, None
|
||||
|
||||
command = content[len(self.command_prefix):].split()[0]
|
||||
if command not in self.commands:
|
||||
return False, None
|
||||
|
||||
# 获取需要总结的内容
|
||||
group_id = message.get("roomid")
|
||||
if not group_id:
|
||||
# 直接发送消息
|
||||
wcf = message.get("wcf")
|
||||
if wcf:
|
||||
wcf.send_text("只支持群聊消息总结", message.get("sender"))
|
||||
return True, None
|
||||
|
||||
# 从消息历史中获取群聊记录
|
||||
# 这里需要根据实际情况从系统上下文或数据库中获取群聊记录
|
||||
# 为简化示例,这里假设从消息中提取
|
||||
chat_content = self.message_storage.get_messages(group_id, self.all_contacts)
|
||||
if len(chat_content) < 100:
|
||||
return False, None
|
||||
# 生成总结
|
||||
summary, image_path = self._generate_summary(chat_content, self.all_contacts.get(group_id, group_id))
|
||||
|
||||
# 发送总结结果
|
||||
wcf = message.get("wcf")
|
||||
if wcf:
|
||||
if summary:
|
||||
wcf.send_text(f"总结已生成:\n{summary}", group_id, message.get("sender"))
|
||||
|
||||
if image_path:
|
||||
wcf.send_file(image_path, group_id)
|
||||
|
||||
return True, None
|
||||
|
||||
except Exception as e:
|
||||
print(f"处理消息总结命令失败: {e}")
|
||||
return False, None
|
||||
|
||||
def _generate_summary(self, chat_content: str, group_id: str) -> Tuple[str, Optional[str]]:
|
||||
"""生成总结"""
|
||||
"""
|
||||
使用Dify API生成群聊消息总结
|
||||
|
||||
Args:
|
||||
content: 需要总结的群聊消息内容
|
||||
|
||||
Returns:
|
||||
生成的总结内容和图片路径
|
||||
"""
|
||||
# Dify API配置
|
||||
content_compress = chat_content
|
||||
try:
|
||||
content_compress = compress_chat_data(chat_content)
|
||||
print(f"压缩内容成功:{len(content_compress)}--{len(chat_content)}")
|
||||
except Exception as e:
|
||||
print(f"压缩内容失败:{e}")
|
||||
|
||||
# 准备请求数据
|
||||
data = {
|
||||
"inputs": {},
|
||||
"query": f"请根据以下{group_id}群聊记录生成一份精华总结:\n\n{content_compress}",
|
||||
"response_mode": "blocking", # 使用阻塞模式,直接获取完整响应
|
||||
"conversation_id": "",
|
||||
"user": group_id if group_id is not None else "message_summary_bot",
|
||||
"files": [] # 不包含文件
|
||||
}
|
||||
|
||||
# 设置请求头
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self._api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
try:
|
||||
# 发送POST请求
|
||||
response = requests.post(self._api_url, headers=headers, json=data)
|
||||
response.raise_for_status() # 检查请求是否成功
|
||||
|
||||
# 解析响应
|
||||
response_data = response.json()
|
||||
print(f"Dify API响应状态码: {response.status_code}")
|
||||
print(f"响应数据: {json.dumps(response_data, ensure_ascii=False, indent=2)}")
|
||||
|
||||
# 提取回答内容
|
||||
answer = response_data.get("answer", "")
|
||||
spath = ""
|
||||
# 提取token使用情况
|
||||
metadata = response_data.get("metadata", {})
|
||||
usage = metadata.get("usage", {})
|
||||
|
||||
if usage:
|
||||
prompt_tokens = usage.get("prompt_tokens", 0)
|
||||
completion_tokens = usage.get("completion_tokens", 0)
|
||||
total_tokens = usage.get("total_tokens", 0)
|
||||
|
||||
# 添加token信息
|
||||
tokens_info = f"\n\n【tokens】输入: {prompt_tokens} 生成: {completion_tokens} 总: {total_tokens}"
|
||||
answer += tokens_info
|
||||
try:
|
||||
spath = convert_md_str_to_image(answer, "output.png")
|
||||
except Exception as e:
|
||||
print(f"生成image失败:{e}")
|
||||
# 返回文本内容和图片路径
|
||||
return answer, spath
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"请求Dify API时出错: {e}")
|
||||
return f"生成总结时出错: {str(e)}", None
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"解析Dify API响应时出错: {e}")
|
||||
return "解析API响应时出错", None
|
||||
|
||||
except Exception as e:
|
||||
print(f"处理总结时出现未知错误: {e}")
|
||||
return f"生成总结时出现未知错误: {str(e)}", None
|
||||
Reference in New Issue
Block a user