From dba16e99c27025285b89854fb3e2ab97998923a2 Mon Sep 17 00:00:00 2001 From: slhaf Date: Sat, 7 Dec 2024 15:08:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BAOpenAI=E8=A7=84?= =?UTF-8?q?=E8=8C=83=20=E5=8E=BB=E9=99=A4=E4=BA=86=E5=8D=95=E6=AC=A1?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=20=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E4=BF=AE=E6=94=B9=20=E5=BE=85=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 + src/main/java/plugin/App.java | 58 ++- src/main/java/plugin/chat/ChatClient.java | 108 +++++ .../plugin/{ => chat}/constant/Constant.java | 16 +- src/main/java/plugin/chat/pojo/ChatBody.java | 25 ++ .../java/plugin/chat/pojo/ChatResponse.java | 16 + src/main/java/plugin/chat/pojo/Message.java | 14 + .../plugin/chat/pojo/PrimaryChatResponse.java | 111 ++++++ src/main/java/plugin/config/AliOCRConfig.java | 23 ++ src/main/java/plugin/config/Config.java | 202 ++++++++++ .../plugin/config/CustomCommandTemplate.java | 25 ++ .../plugin/config/ModelConfigTemplate.java | 14 + src/main/java/plugin/constant/AIConstant.java | 18 - .../java/plugin/constant/ChatConstant.java | 46 --- .../java/plugin/constant/ConfigConstant.java | 15 - .../java/plugin/constant/MethodsConstant.java | 6 - .../listener/FriendMessageListener.java | 44 +-- .../plugin/listener/GroupMessageListener.java | 58 ++- .../plugin/listener/OwnerMessageListener.java | 106 ++--- src/main/java/plugin/pojo/Config.java | 226 ----------- src/main/java/plugin/pojo/OCRDataInfo.java | 77 +--- .../plugin/pojo/UserCustomLatestTime.java | 62 --- .../java/plugin/pojo/UserCustomMessage.java | 57 --- src/main/java/plugin/utils/AIUtil.java | 370 ------------------ src/main/java/plugin/utils/ChatUtil.java | 110 ++++++ src/main/java/plugin/utils/ConfigUtil.java | 199 ---------- src/main/java/plugin/utils/OCRUtil.java | 29 +- src/test/java/MyTest.java | 60 --- 28 files changed, 827 insertions(+), 1269 deletions(-) create mode 100644 src/main/java/plugin/chat/ChatClient.java rename src/main/java/plugin/{ => chat}/constant/Constant.java (77%) create mode 100644 src/main/java/plugin/chat/pojo/ChatBody.java create mode 100644 src/main/java/plugin/chat/pojo/ChatResponse.java create mode 100644 src/main/java/plugin/chat/pojo/Message.java create mode 100644 src/main/java/plugin/chat/pojo/PrimaryChatResponse.java create mode 100644 src/main/java/plugin/config/AliOCRConfig.java create mode 100644 src/main/java/plugin/config/Config.java create mode 100644 src/main/java/plugin/config/CustomCommandTemplate.java create mode 100644 src/main/java/plugin/config/ModelConfigTemplate.java delete mode 100644 src/main/java/plugin/constant/AIConstant.java delete mode 100644 src/main/java/plugin/constant/ChatConstant.java delete mode 100644 src/main/java/plugin/constant/ConfigConstant.java delete mode 100644 src/main/java/plugin/pojo/Config.java delete mode 100644 src/main/java/plugin/pojo/UserCustomLatestTime.java delete mode 100644 src/main/java/plugin/pojo/UserCustomMessage.java delete mode 100644 src/main/java/plugin/utils/AIUtil.java create mode 100644 src/main/java/plugin/utils/ChatUtil.java delete mode 100644 src/main/java/plugin/utils/ConfigUtil.java diff --git a/build.gradle.kts b/build.gradle.kts index 06a3bd2..d88da82 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,6 +20,7 @@ dependencies{ implementation ("org.apache.logging.log4j:log4j-api:2.23.1") implementation("top.mrxiaom.mirai:overflow-core-api:1.0.0.519-0d68f08-SNAPSHOT") implementation ("com.alibaba:fastjson:1.2.73") + implementation ("org.projectlombok:lombok:1.18.36") } diff --git a/src/main/java/plugin/App.java b/src/main/java/plugin/App.java index 8f5d415..1a9ab4b 100644 --- a/src/main/java/plugin/App.java +++ b/src/main/java/plugin/App.java @@ -6,16 +6,15 @@ import net.mamoe.mirai.event.GlobalEventChannel; import net.mamoe.mirai.event.events.FriendMessageEvent; import net.mamoe.mirai.event.events.GroupMessageEvent; import net.mamoe.mirai.event.events.MessageEvent; -import plugin.constant.ChatConstant; -import plugin.constant.Constant; +import plugin.chat.constant.Constant; +import plugin.config.Config; +import plugin.config.CustomCommandTemplate; import plugin.listener.FriendMessageListener; import plugin.listener.GroupMessageListener; import plugin.listener.OwnerMessageListener; -import plugin.pojo.Config; -import plugin.utils.ConfigUtil; import java.io.IOException; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; @@ -36,28 +35,30 @@ public final class App extends JavaPlugin { @Override public void onEnable() { String owner, bot; - HashMap customCommands; + ArrayList customCommands; List blacklist; //加载配置 try { - ConfigUtil.load(); - Thread.sleep(1500); - Config config = ConfigUtil.getConfig(); + Config config = Config.ConfigLoader.load(); + App.class.getClassLoader().loadClass("plugin.utils.OCRUtil"); + App.class.getClassLoader().loadClass("plugin.utils.ChatUtil"); + owner = config.getOwner().substring(1); bot = config.getBot().substring(1); - customCommands = config.getCustomCommands(); + customCommands = config.getCustomCommandTemplates(); blacklist = config.getBlacklist(); - } catch (IOException | ClassNotFoundException | InterruptedException e) { + } catch (IOException | ClassNotFoundException e) { throw new RuntimeException(e); } - getLogger().info("ChatAI-InGroup loaded!"); + getLogger().info("ChatAI loaded!"); //群聊监听器 GlobalEventChannel.INSTANCE.filterIsInstance(GroupMessageEvent.class) .filter(event -> { String msg = event.getMessage().contentToString(); long groupId = event.getGroup().getId(); - return ((msg.startsWith(Constant.Order.PREFIX_ONECE) && msg.length() != 1) || msg.startsWith(Constant.Order.PREFIX_DEFAULT + bot) || customCommands.containsKey(msg.split(Constant.Order.SPLIT_BLANK)[0] + Constant.Order.SPLIT_BLANK)) && !blacklist.contains(groupId); + String prefix = msg.split(Constant.Order.SPLIT_BLANK)[0]; + return (msg.startsWith(Constant.Order.PREFIX_DEFAULT + bot) || checkCommandExist(prefix,customCommands)) && !blacklist.contains(groupId); }).registerListenerHost(new GroupMessageListener()); //私聊监听器 @@ -65,7 +66,10 @@ public final class App extends JavaPlugin { .filter(event -> { String msg = event.getMessage().contentToString(); String sender = String.valueOf(event.getFriend().getId()); - return !(msg.startsWith(Constant.Order.PREFIX_SET) && sender.equals(owner)) && !msg.equals(Constant.Order.MSG_HELP); + String prefix = msg.split(Constant.Order.SPLIT_BLANK)[0]; +// return !(msg.startsWith(Constant.Order.PREFIX_SET) && sender.equals(owner)) && !msg.equals(Constant.Order.MSG_HELP); + return checkCommandExist(prefix,customCommands) //包含指令前缀 + || !((msg.startsWith(Constant.Order.PREFIX_SET) && sender.equals(owner)) || msg.startsWith(Constant.Order.PREFIX_CUSTOM)); //如果不包含指令前缀,则不能以设置指令、"/"开头 }).registerListenerHost(new FriendMessageListener()); //所有者监听 @@ -97,25 +101,41 @@ public final class App extends JavaPlugin { $ clearAll (仅限群聊) $ shutUp (仅限群聊) $ speak (仅限群聊) - $ 添加预设|<预设指令>|<模型名称/null>|<预设内容> - $ 切换模型|<预设指令>|<模型名称> + $ 添加预设|<预设指令>|<模型模板ID>|<模型名称>|<预设内容> + $ 切换模型|<预设指令>|<模型模板ID>|<模型名称> $ 更改预设|<预设指令>|<预设内容> $ 删除预设|<预设指令> 例: - $ 添加预设|/c|glm-4-flash|你是一只猫娘... + $ 添加预设|/c|<模型模板ID>|glm-4-flash|你是一只猫娘... """}; helpMsg[0] += "————<预设列表>————"; - customCommands.forEach((s, s2) -> helpMsg[0] += "\r\n\r\n" + s + "-> \r\n" + s2); + for (CustomCommandTemplate customCommand : customCommands) { + helpMsg[0] += "\r\n\r\n"+customCommand.toString(); + } + helpMsg[0] += "\r\n"; + helpMsg[0] += "————<模型列表>————"; + for (int i = 0; i < Config.ConfigLoader.getConfig().getModelConfigTemplates().size(); i++) { + helpMsg[0] += "\r\n\r\n"+"TemplateIndex: "+i+"\r\n"+Config.ConfigLoader.getConfig().getModelConfigTemplates().get(i).toString(); + } event.getSubject().sendMessage(helpMsg[0]); } }); } + private boolean checkCommandExist(String prefix, ArrayList customCommands) { + for (CustomCommandTemplate customCommand : customCommands) { + if (customCommand.getCommand().equals(prefix)) { + return true; + } + } + return false; + } + @Override public void onDisable() { getLogger().info("ChatAI-InGroup disabled!"); } -} \ No newline at end of file +} diff --git a/src/main/java/plugin/chat/ChatClient.java b/src/main/java/plugin/chat/ChatClient.java new file mode 100644 index 0000000..9ed5350 --- /dev/null +++ b/src/main/java/plugin/chat/ChatClient.java @@ -0,0 +1,108 @@ +package plugin.chat; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.json.JSONUtil; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import plugin.chat.constant.Constant; +import plugin.chat.pojo.ChatBody; +import plugin.chat.pojo.ChatResponse; +import plugin.chat.pojo.Message; +import plugin.chat.pojo.PrimaryChatResponse; + +import java.util.ArrayList; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ChatClient { + private String clientId; + + private String url; + private String apikey; + private String model; + + private int top_p; + private int temperature; + private int max_tokens; + + private List messages = new ArrayList<>(); + + public ChatClient(String clientId,String url,String apikey,String model){ + this(url, apikey,model); + this.clientId = clientId; + } + + public ChatClient(String clientId,String url, String apikey,String model, int top_p, int temperature, int max_tokens) { + this(url, apikey,model, top_p, temperature, max_tokens); + this.clientId = clientId; + } + + public ChatClient(String url, String apikey,String model, int top_p, int temperature, int max_tokens) { + this(url, apikey,model); + this.top_p = top_p; + this.temperature = temperature; + this.max_tokens = max_tokens; + } + + public ChatClient(String url,String apikey,String model){ + this.url = url; + this.apikey = apikey; + this.model = model; + } + + public void setPromotion(String promotion){ + Message message = Message.builder() + .role(Constant.Character.SYSTEM) + .content(promotion) + .build(); + messages.add(0,message); + } + + public ChatResponse runChat(String content){ + HttpRequest request = HttpRequest.post(url+"/chat/completions"); + request.header("Content-Type", "application/json"); + request.header("Authorization", "Bearer " + apikey); + + Message message = new Message(Constant.Character.USER,content); + messages.add(message); + ChatBody body; + if (top_p > 0) { + body = ChatBody.builder() + .model(model) + .messages(messages) + .top_p(top_p) + .temperature(temperature) + .max_tokens(max_tokens) + .build(); + }else { + body = ChatBody.builder() + .model(model) + .messages(messages) + .build(); + } + + HttpResponse response = request.body(JSONUtil.toJsonStr(body)).execute(); + ChatResponse finalResponse; + try { + PrimaryChatResponse primaryChatResponse = JSONUtil.toBean(response.body(), PrimaryChatResponse.class); + finalResponse = ChatResponse.builder() + .type(Constant.Response.SUCCESS) + .message(primaryChatResponse.getChoices().get(0).getMessage().getContent()) + .usageBean(primaryChatResponse.getUsage()) + .build(); + messages.add(new Message(Constant.Character.SYSTEM, finalResponse.getMessage())); + }catch (Exception e){ + finalResponse = ChatResponse.builder() + .type(Constant.Response.ERROR) + .message(response.getStatus()+": "+response.body()) + .build(); + } + response.close(); + return finalResponse; + } + +} diff --git a/src/main/java/plugin/constant/Constant.java b/src/main/java/plugin/chat/constant/Constant.java similarity index 77% rename from src/main/java/plugin/constant/Constant.java rename to src/main/java/plugin/chat/constant/Constant.java index 0b5548e..95625aa 100644 --- a/src/main/java/plugin/constant/Constant.java +++ b/src/main/java/plugin/chat/constant/Constant.java @@ -1,4 +1,4 @@ -package plugin.constant; +package plugin.chat.constant; public class Constant { public static class Character{ @@ -42,9 +42,21 @@ public class Constant { public static final String DEFAULT = "default"; public static final String NULL = "null"; + public static final String MSG_STATUS = "/status"; + public static final String PREFIX_CUSTOM = "/"; + public static final String MODEL_CHANGE = ".*\\|.*"; } public static class StatusCode { - public static final int OK = "200"; + public static final int OK = 200; + } + + public static class Response { + public static final String SUCCESS = "success"; + public static final String ERROR = "error"; + } + + public static class Path { + public static final String CONFIG_PATH = "./config/ChatAI/config.yaml"; } } diff --git a/src/main/java/plugin/chat/pojo/ChatBody.java b/src/main/java/plugin/chat/pojo/ChatBody.java new file mode 100644 index 0000000..e5cbf27 --- /dev/null +++ b/src/main/java/plugin/chat/pojo/ChatBody.java @@ -0,0 +1,25 @@ +package plugin.chat.pojo; + +import lombok.*; + +import java.util.List; + +@Builder +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ChatBody { + @NonNull + private String model; + @NonNull + private List messages; + @Builder.Default + private int temperature = 1; + @Builder.Default + private int top_p = 1; + private boolean stream; + @Builder.Default + private int max_tokens = 1024; + private int presence_penalty; + private int frequency_penalty; +} diff --git a/src/main/java/plugin/chat/pojo/ChatResponse.java b/src/main/java/plugin/chat/pojo/ChatResponse.java new file mode 100644 index 0000000..9b8c0cf --- /dev/null +++ b/src/main/java/plugin/chat/pojo/ChatResponse.java @@ -0,0 +1,16 @@ +package plugin.chat.pojo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ChatResponse { + private String type; + private String message; + private PrimaryChatResponse.UsageBean usageBean; +} diff --git a/src/main/java/plugin/chat/pojo/Message.java b/src/main/java/plugin/chat/pojo/Message.java new file mode 100644 index 0000000..8f0a849 --- /dev/null +++ b/src/main/java/plugin/chat/pojo/Message.java @@ -0,0 +1,14 @@ +package plugin.chat.pojo; + +import lombok.*; + +@Builder +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Message { + @NonNull + private String role; + @NonNull + private String content; +} diff --git a/src/main/java/plugin/chat/pojo/PrimaryChatResponse.java b/src/main/java/plugin/chat/pojo/PrimaryChatResponse.java new file mode 100644 index 0000000..4456804 --- /dev/null +++ b/src/main/java/plugin/chat/pojo/PrimaryChatResponse.java @@ -0,0 +1,111 @@ +package plugin.chat.pojo; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class PrimaryChatResponse { + + /** + * id + */ + private String id; + /** + * object + */ + private String object; + /** + * created + */ + private int created; + /** + * model + */ + private String model; + /** + * choices + */ + private List choices; + /** + * usage + */ + private UsageBean usage; + /** + * system_fingerprint + */ + private String system_fingerprint; + + @Setter + @Getter + public static class UsageBean { + /** + * prompt_tokens + */ + private int prompt_tokens; + /** + * completion_tokens + */ + private int completion_tokens; + /** + * total_tokens + */ + private int total_tokens; + /** + * prompt_cache_hit_tokens + */ + private int prompt_cache_hit_tokens; + /** + * prompt_cache_miss_tokens + */ + private int prompt_cache_miss_tokens; + + @Override + public String toString() { + return "UsageBean{" + + "prompt_tokens=" + prompt_tokens + + ", completion_tokens=" + completion_tokens + + ", total_tokens=" + total_tokens + + ", prompt_cache_hit_tokens=" + prompt_cache_hit_tokens + + ", prompt_cache_miss_tokens=" + prompt_cache_miss_tokens + + '}'; + } + } + + @Setter + @Getter + public static class ChoicesBean { + /** + * index + */ + private int index; + /** + * message + */ + private MessageBean message; + /** + * logprobs + */ + private Object logprobs; + /** + * finish_reason + */ + private String finish_reason; + + @Setter + @Getter + public static class MessageBean { + /** + * role + */ + private String role; + /** + * content + */ + private String content; + + } + } +} diff --git a/src/main/java/plugin/config/AliOCRConfig.java b/src/main/java/plugin/config/AliOCRConfig.java new file mode 100644 index 0000000..2e87f9b --- /dev/null +++ b/src/main/java/plugin/config/AliOCRConfig.java @@ -0,0 +1,23 @@ +package plugin.config; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class AliOCRConfig { + private String accessKeyId; + private String accessKeySecret; + + public AliOCRConfig() { + } + + public AliOCRConfig(String accessKeyId, String accessKeySecret) { + this.accessKeyId = accessKeyId; + this.accessKeySecret = accessKeySecret; + } + + public String toString() { + return "AliOCRConfig{accessKeyId = " + accessKeyId + ", accessKeySecret = " + accessKeySecret + "}"; + } +} diff --git a/src/main/java/plugin/config/Config.java b/src/main/java/plugin/config/Config.java new file mode 100644 index 0000000..3c569f1 --- /dev/null +++ b/src/main/java/plugin/config/Config.java @@ -0,0 +1,202 @@ +package plugin.config; + +import cn.hutool.core.bean.BeanUtil; +import lombok.Getter; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.Yaml; +import plugin.chat.constant.Constant; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + + +@Setter +@Getter +@Slf4j +public class Config { + + /** + * owner QQ + */ + private String owner; + + /** + * bot QQ + */ + private String bot; + + /** + * 对话记录过期时间 + */ + private String timeout; + + /** + * 检测对话记录间隔 + */ + private String timeCheck; + + /** + * 群聊黑名单 + */ + private List blacklist; + + /** + * 阿里OCR配置 + */ + private AliOCRConfig ocrConfig; + + /** + * 模板配置 + */ + private List modelConfigTemplates; + + /** + * 预设配置 + */ + private ArrayList customCommandTemplates; + + private Config() { + } + + public static class ConfigLoader { + private static final Yaml yaml; + @Getter + private static Config config; + + static { + DumperOptions options = new DumperOptions(); + options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + yaml = new Yaml(options); + } + + public static Config load() throws IOException { + Config config; + DumperOptions dumperOptions = new DumperOptions(); + dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); + Yaml yaml = new Yaml(dumperOptions); + File file = new File(Constant.Path.CONFIG_PATH); + if (file.exists()) { + FileInputStream fileInputStream = new FileInputStream(Constant.Path.CONFIG_PATH); + config = BeanUtil.toBean(yaml.load(fileInputStream), Config.class); + fileInputStream.close(); + log.info("load config success"); + } else { + file.getParentFile().mkdirs(); + file.createNewFile(); + config = new Config(); + //基础配置 + config.setOwner("your_bot_owner_qq_number(e.g. Q1145141919810)"); + config.setBot("your_bot_qq_number(e.g. Q1145141919810)"); + config.setTimeout("M3600000"); + config.setTimeCheck("M60000"); + ArrayList blacklist = new ArrayList<>(); + blacklist.add(123456789L); + blacklist.add(987654321L); + config.setBlacklist(blacklist); + + //OCR配置 + config.setOcrConfig(new AliOCRConfig("ocr_accessKeyId", "ocr_accessKeySecret")); + + //模型模板 + List templateList = new ArrayList<>(); + templateList.add(new ModelConfigTemplate("zhipu", "https://open.bigmodel.cn/api/paas/v4", "zhipu_apikey")); + templateList.add(new ModelConfigTemplate("deepseek", "https://api.deepseek.com/v1", "deepseek_apikey")); + config.setModelConfigTemplates(templateList); + + //自定义预设 + ArrayList customCommands = new ArrayList<>(); + customCommands.add(new CustomCommandTemplate("default", 0, "glm-4-flash", "null")); + customCommands.add(new CustomCommandTemplate("/c", 0, "glm-4-flash", "你是一位智能编程助手,你会为用户回答关于编程、代码、计算机方面的任何问题,并提供格式规范、可以执行、准确安全的代码,并在必要时提供详细的解释。 请用中文回答。")); + config.setCustomCommandTemplates(customCommands); + dump(); + log.warn("配置文件创建成功,请关闭后进行配置"); + System.exit(0); + } + ConfigLoader.config = config; + return config; + } + + private static void dump() throws IOException { + FileWriter fileWriter = new FileWriter(Constant.Path.CONFIG_PATH); + yaml.dump(BeanUtil.beanToMap(config), fileWriter); + } + + /** + * 关闭当前群聊发言 + * + * @param id 群聊id + */ + public static String shutUp(long id) { + config.getBlacklist().add(id); + return "ChatAI-InGroup 已关闭"; + } + + /** + * 开启当前群聊发言 + * + * @param id 群聊id + */ + public static String speak(long id) { + config.getBlacklist().remove(id); + return "ChatAI-InGroup 已开启"; + } + + /** + * 添加预设 + * + * @param command + * @param modelTemplateIndex + * @param customModel + * @param customPromotion + * @return + * @throws IOException + */ + public static String addCustom(String command, int modelTemplateIndex, String customModel, String customPromotion) throws IOException { + ArrayList customCommands = config.getCustomCommandTemplates(); + synchronized (customCommands) { + for (CustomCommandTemplate customCommand : customCommands) { + if (customCommand.getCommand().equals(command)) { + return "当前指令已存在!\r\n" + customCommand; + } + } + CustomCommandTemplate customCommand = new CustomCommandTemplate(command, modelTemplateIndex, customModel, customPromotion); + customCommands.add(customCommand); + dump(); + return "预设添加完毕!\r\n" + customCommand; + } + } + + /** + * 删除预设 + * + * @param command + * @return + */ + public static String removeCustom(String command) { + if (command.equals(Constant.Order.DEFAULT)) { + return "该预设不可删除!"; + } + ArrayList customCommands = config.getCustomCommandTemplates(); + int index = -1; + for (int i = 0; i < customCommands.size(); i++) { + if (customCommands.get(i).getCommand().equals(command)) { + index = i; + } + } + if (index == -1) { + return "该预设不存在!"; + } + return "预设删除完毕" + customCommands.remove(index); + } + + + } + + +} diff --git a/src/main/java/plugin/config/CustomCommandTemplate.java b/src/main/java/plugin/config/CustomCommandTemplate.java new file mode 100644 index 0000000..292b7e1 --- /dev/null +++ b/src/main/java/plugin/config/CustomCommandTemplate.java @@ -0,0 +1,25 @@ +package plugin.config; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class CustomCommandTemplate { + private String command; + private int modelTemplateIndex; + private String customModel; + private String customPromotion; + + @Override + public String toString() { + return "command: " + command + "\r\n" + + "modelTemplateIndex: " + modelTemplateIndex + "\r\n" + + "customModel: " + customModel + "\r\n" + + "customPromotion: " + customPromotion + "\r\n"; + } +} diff --git a/src/main/java/plugin/config/ModelConfigTemplate.java b/src/main/java/plugin/config/ModelConfigTemplate.java new file mode 100644 index 0000000..1575eef --- /dev/null +++ b/src/main/java/plugin/config/ModelConfigTemplate.java @@ -0,0 +1,14 @@ +package plugin.config; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ModelConfigTemplate { + private String template_name; + private String base_url; + private String apikey; +} diff --git a/src/main/java/plugin/constant/AIConstant.java b/src/main/java/plugin/constant/AIConstant.java deleted file mode 100644 index 9d9509d..0000000 --- a/src/main/java/plugin/constant/AIConstant.java +++ /dev/null @@ -1,18 +0,0 @@ -package plugin.constant; - -/** - * @author SLHAF - */ -public class AIConstant { - /** - * 当前模型 - */ - public static final String CURRENT_MODEL = "当前模型"; - - - /** - * 错误结果 - */ - public static final String ERROR = "ERROR"; - public static final int NORMAL_CODE = 200; -} diff --git a/src/main/java/plugin/constant/ChatConstant.java b/src/main/java/plugin/constant/ChatConstant.java deleted file mode 100644 index e1d44ba..0000000 --- a/src/main/java/plugin/constant/ChatConstant.java +++ /dev/null @@ -1,46 +0,0 @@ -package plugin.constant; - -/** - * @author SLHAF - */ -public class ChatConstant { - - /** - * 匹配含有图片信息的消息 - */ - public static final String MATCH_MESSAGE = ".*[mirai:image:(https?://[\\w./?&=]+)].*"; - - /** - * 匹配图片信息 - */ - public static final String MATCH_IMAGE = "\\[mirai:image:(.*?)]"; - - /** - * 单次对话标志 - */ - public static final String ONCE_MESSAGE_START = "."; - - /** - * 普通对话标志 - */ - public static final String DEFAULT_MESSAGE_START = "@"; - - /** - * 分隔符(空格) - */ - public static final String BLANK = " "; - - public static final String SET = "$ "; - - /** - * 清理消息 - */ - public static final String CLEAR = "clear"; - - /** - * 当前模型 - */ - public static final String CURRENT_MODEL = "当前模型"; - public static final String SPLIT = "|"; - public static final String HELP = "/chatHelp"; -} diff --git a/src/main/java/plugin/constant/ConfigConstant.java b/src/main/java/plugin/constant/ConfigConstant.java deleted file mode 100644 index 15bb813..0000000 --- a/src/main/java/plugin/constant/ConfigConstant.java +++ /dev/null @@ -1,15 +0,0 @@ -package plugin.constant; - -/** - * @author SLHAF - */ -public class ConfigConstant { - - public static final String DEFAULT = "default"; - - public static final String NULL = "null"; - - public static final String CUSTOM_SPLIT = "\\|"; - public static final String ADD_CUSTOM = "/[a-zA-Z]+\\|.*\\|.*"; - public static final String MODEL_CHANGE = ".*\\|.*"; -} diff --git a/src/main/java/plugin/constant/MethodsConstant.java b/src/main/java/plugin/constant/MethodsConstant.java index 7cffce8..8d836ca 100644 --- a/src/main/java/plugin/constant/MethodsConstant.java +++ b/src/main/java/plugin/constant/MethodsConstant.java @@ -6,16 +6,10 @@ public enum MethodsConstant { * 正常对话 */ NORMAL, - - /** - * 单次对话 - */ - ONCE, /** * 预设对话 */ CUSTOM, - /** * 未匹配 */ diff --git a/src/main/java/plugin/listener/FriendMessageListener.java b/src/main/java/plugin/listener/FriendMessageListener.java index 55bb592..9065933 100644 --- a/src/main/java/plugin/listener/FriendMessageListener.java +++ b/src/main/java/plugin/listener/FriendMessageListener.java @@ -3,10 +3,9 @@ package plugin.listener; import net.mamoe.mirai.event.EventHandler; import net.mamoe.mirai.event.SimpleListenerHost; import net.mamoe.mirai.event.events.FriendMessageEvent; -import plugin.constant.ChatConstant; -import plugin.constant.MethodsConstant; -import plugin.utils.AIUtil; -import plugin.utils.ConfigUtil; +import plugin.chat.constant.Constant; +import plugin.utils.ChatUtil; +import plugin.utils.OCRUtil; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -22,9 +21,9 @@ public class FriendMessageListener extends SimpleListenerHost { String content = event.getMessage().contentToString(); String miraiCode = event.getMessage().serializeToMiraiCode(); String url = null; - String chatCommand = null; - if (miraiCode.matches(ChatConstant.MATCH_MESSAGE)) { - String regex = ChatConstant.MATCH_IMAGE; + String chatCommand; + if (miraiCode.matches(Constant.Regex.MATCH_MESSAGE)) { + String regex = Constant.Regex.MATCH_IMAGE; Pattern pattern = Pattern.compile(regex); // 创建Matcher对象 @@ -36,25 +35,26 @@ public class FriendMessageListener extends SimpleListenerHost { url = matcher.group(1); } } - MethodsConstant method = MethodsConstant.NORMAL; + if (OCRUtil.isSupported && url != null) { + content = content + "```content\r\n" + OCRUtil.getContentOfImage(url) + "\r\n```"; + } //处理消息头 - if (ConfigUtil.getConfig().getCustomCommands().containsKey(content.split(ChatConstant.BLANK)[0]+ChatConstant.BLANK)) { - String[] split = content.split(ChatConstant.BLANK); - chatCommand = split[0] + ChatConstant.BLANK; - method = MethodsConstant.CUSTOM; - content = content.substring((content.split(ChatConstant.BLANK)[0]+ChatConstant.BLANK).length()); - } else if (content.startsWith(ChatConstant.ONCE_MESSAGE_START)) { - content = content.substring(1); - method = MethodsConstant.ONCE; + if (content.startsWith(Constant.Order.PREFIX_CUSTOM)) { + chatCommand = content.split(Constant.Order.SPLIT_BLANK)[0]; + content = content.substring(chatCommand.length() + 1); + } else { + chatCommand = Constant.Order.DEFAULT; } //发送请求并获取回应 - String response = switch (method) { - case CUSTOM -> AIUtil.customChat(Long.valueOf(id), content, url, chatCommand); - case ONCE -> AIUtil.chatOnce(content, url); - case NORMAL -> AIUtil.defaultChat(Long.valueOf(id), content, url); - default -> "ERROR!"; - }; + String response; + if (content.equals(Constant.Order.MSG_CLEAR)){ + //检测是否为清除指令 + response = ChatUtil.removeClient(id, chatCommand); + }else { + //发送请求并获取回应 + response = ChatUtil.chat(id, content, chatCommand); + } event.getFriend().sendMessage(response); } } diff --git a/src/main/java/plugin/listener/GroupMessageListener.java b/src/main/java/plugin/listener/GroupMessageListener.java index c190fef..6b300f0 100644 --- a/src/main/java/plugin/listener/GroupMessageListener.java +++ b/src/main/java/plugin/listener/GroupMessageListener.java @@ -1,47 +1,36 @@ package plugin.listener; -import kotlin.coroutines.CoroutineContext; +import lombok.extern.slf4j.Slf4j; import net.mamoe.mirai.event.EventHandler; import net.mamoe.mirai.event.SimpleListenerHost; import net.mamoe.mirai.event.events.GroupMessageEvent; import net.mamoe.mirai.message.data.At; -import org.jetbrains.annotations.NotNull; -import plugin.constant.ChatConstant; -import plugin.constant.Constant; -import plugin.constant.MethodsConstant; -import plugin.pojo.Config; -import plugin.utils.AIUtil; -import plugin.utils.ConfigUtil; +import plugin.chat.constant.Constant; +import plugin.utils.ChatUtil; +import plugin.utils.OCRUtil; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static plugin.utils.ConfigUtil.logger; - /** * @author SLHAF */ +@Slf4j public class GroupMessageListener extends SimpleListenerHost { - @Override - public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) { - logger.warning(exception); - } - /** * 负责提取链接、获取消息内容(去除指令头),提取指令、提取发送者id * @param event 接收群聊消息 */ @EventHandler public void groupMessageHandler(GroupMessageEvent event) { - Config config = ConfigUtil.getConfig(); //处理消息 String id = String.valueOf(event.getSender().getId()); String content = event.getMessage().contentToString(); String miraiCode = event.getMessage().serializeToMiraiCode(); String url = null; - String chatCommand = null; + String chatCommand; if (miraiCode.matches(Constant.Regex.MATCH_MESSAGE)) { Pattern pattern = Pattern.compile(Constant.Regex.MATCH_IMAGE); @@ -54,36 +43,33 @@ public class GroupMessageListener extends SimpleListenerHost { url = matcher.group(1); } } - - MethodsConstant method = MethodsConstant.NONE; + if (OCRUtil.isSupported && url != null) { + content = content + "```content\r\n" + OCRUtil.getContentOfImage(url) + "\r\n```"; + } //消息头处理 - if (content.startsWith(Constant.Order.PREFIX_ONECE)) { - //单次对话 - content = content.substring(1); - method = MethodsConstant.ONCE; - } else if (content.startsWith(Constant.Order.PREFIX_DEFAULT + event.getBot().getId())) { + if (content.startsWith(Constant.Order.PREFIX_DEFAULT + event.getBot().getId())) { //默认对话 content = content.substring((Constant.Order.PREFIX_DEFAULT + event.getBot().getId()).length()); - method = MethodsConstant.NORMAL; - } else if (config.getCustomCommands().containsKey(content.split(Constant.Order.SPLIT_BLANK)[0]+Constant.Order.SPLIT_BLANK)) { + chatCommand = Constant.Order.DEFAULT; + } else { //预设对话 String[] split = content.split(Constant.Order.SPLIT_BLANK); - chatCommand = split[0] + Constant.Order.SPLIT_BLANK; - method = MethodsConstant.CUSTOM; - content = content.substring(chatCommand.length()); + chatCommand = split[0]; + content = content.substring(chatCommand.length()+1); } //消息内容处理 if (content.isBlank()) { content = "在吗"; } - //发送请求并获取回应 - String response = switch (method) { - case CUSTOM -> AIUtil.customChat(Long.valueOf(id), content, url,chatCommand); - case NORMAL -> AIUtil.defaultChat(Long.valueOf(id), content, url); - case ONCE -> AIUtil.chatOnce(content, url); - default -> Constant.Status.ERROR; - }; + String response; + if (content.equals(Constant.Order.MSG_CLEAR)){ + //检测是否为清除指令 + response = ChatUtil.removeClient(id, chatCommand); + }else { + //发送请求并获取回应 + response = ChatUtil.chat(id, content, chatCommand); + } event.getGroup().sendMessage(new At(Long.parseLong(id)).plus("\r\n").plus(response)); } } diff --git a/src/main/java/plugin/listener/OwnerMessageListener.java b/src/main/java/plugin/listener/OwnerMessageListener.java index a09f2b8..0939226 100644 --- a/src/main/java/plugin/listener/OwnerMessageListener.java +++ b/src/main/java/plugin/listener/OwnerMessageListener.java @@ -1,6 +1,6 @@ package plugin.listener; -import kotlin.coroutines.CoroutineContext; +import lombok.extern.slf4j.Slf4j; import net.mamoe.mirai.contact.Group; import net.mamoe.mirai.event.EventHandler; import net.mamoe.mirai.event.SimpleListenerHost; @@ -8,28 +8,19 @@ import net.mamoe.mirai.event.events.FriendMessageEvent; import net.mamoe.mirai.event.events.GroupMessageEvent; import net.mamoe.mirai.event.events.MessageEvent; import net.mamoe.mirai.message.data.At; -import org.jetbrains.annotations.NotNull; -import plugin.constant.ChatConstant; -import plugin.constant.Constant; -import plugin.constant.ConfigConstant; -import plugin.utils.AIUtil; -import plugin.utils.ConfigUtil; +import plugin.chat.constant.Constant; +import plugin.config.Config; +import plugin.config.CustomCommandTemplate; +import plugin.utils.ChatUtil; import java.io.IOException; -import static plugin.utils.ConfigUtil.logger; - /** * @author SLHAF */ +@Slf4j public class OwnerMessageListener extends SimpleListenerHost { - @Override - public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) { - super.handleException(context, exception); - logger.error(exception); - } - @EventHandler public void messageClassifier(MessageEvent event) throws IOException { if (event.getSubject() instanceof Group) { @@ -45,23 +36,23 @@ public class OwnerMessageListener extends SimpleListenerHost { if (!primaryContent.contains(Constant.Order.SPLIT_GUN)) { String response; response = switch (primaryContent) { - case "clearAll" -> AIUtil.clearAll(); - case "shutUp" -> ConfigUtil.shutUp(event.getGroup().getId()); - case "speak" -> ConfigUtil.speak(event.getGroup().getId()); + case "clearAll" -> ChatUtil.removeAllClients(); + case "shutUp" -> Config.ConfigLoader.shutUp(event.getGroup().getId()); + case "speak" -> Config.ConfigLoader.speak(event.getGroup().getId()); default -> "无对应操作"; }; event.getGroup().sendMessage(response); return; } - String command = primaryContent.split(Constant.Order.SPLIT_CUSTOM)[0]; + String instruction = primaryContent.split(Constant.Order.SPLIT_CUSTOM)[0]; String arguments = primaryContent.substring(primaryContent.indexOf(Constant.Order.SPLIT_GUN) + 1); long id = event.getSender().getId(); String response; try { - response = handleCommand(command, arguments); + response = handleCommand(instruction, arguments); } catch (Exception e) { - logger.error(e.toString()); + log.error(e.toString()); response = "操作失败!\r\n" + e.getMessage(); } event.getGroup().sendMessage(new At(id).plus(response)); @@ -69,57 +60,84 @@ public class OwnerMessageListener extends SimpleListenerHost { private void onFriendMessageEvent(FriendMessageEvent event) throws IOException { String primaryContent = event.getMessage().contentToString().split(Constant.Order.SPLIT_BLANK)[1]; - String command; + String instruction; String arguments; try { - command = primaryContent.split(ConfigConstant.CUSTOM_SPLIT)[0]; + instruction = primaryContent.split(Constant.Order.SPLIT_CUSTOM)[0]; arguments = primaryContent.substring(primaryContent.indexOf(Constant.Order.SPLIT_CUSTOM) + 1); } catch (ArrayIndexOutOfBoundsException e) { event.getFriend().sendMessage("操作失败,缺少参数"); return; } - String response = handleCommand(command, arguments); + String response = handleCommand(instruction, arguments); event.getFriend().sendMessage(response); } /** * 对命令及其参数进行处理 * - * @param command 命令 + * @param instruction 命令 * @param arguments 参数 * @return 处理结果 */ - private String handleCommand(String command, String arguments) throws IOException { - return switch (command) { + private String handleCommand(String instruction, String arguments) throws IOException { + return switch (instruction) { case "添加预设" -> { - if (arguments.matches(ConfigConstant.ADD_CUSTOM)) { - String instruction = arguments.split(ConfigConstant.CUSTOM_SPLIT)[0] + ChatConstant.BLANK; - String customModel = arguments.split(ConfigConstant.CUSTOM_SPLIT)[1]; - String customContent = arguments.split(ConfigConstant.CUSTOM_SPLIT)[2]; - yield ConfigUtil.addCustom(instruction, customModel, customContent); + if (arguments.matches(Constant.Regex.ADD_CUSTOM)) { + String[] argumentsArray = arguments.split(Constant.Order.SPLIT_CUSTOM); + String command = argumentsArray[0]; + int modelTemplateIndex = Integer.parseInt(argumentsArray[1]); + String customModel = argumentsArray[2]; + String customPromotion = argumentsArray[3]; + if (modelTemplateIndex >= Config.ConfigLoader.getConfig().getModelConfigTemplates().size()){ + yield "不存在模型模板["+modelTemplateIndex+"]"; + } + yield Config.ConfigLoader.addCustom(command,modelTemplateIndex,customModel,customPromotion); } else { - yield "格式不正确! 格式如下: \r\n" + ChatConstant.SET + "命令|预设指令|模型名称|预设\r\n例: \r\n" + ChatConstant.SPLIT + "/example|glm-4-flash|你是...\r\n注:如果不需要预设,可以将预设写为null"; + yield "格式不正确!"; } } case "切换模型" -> { - if (arguments.matches(ConfigConstant.MODEL_CHANGE)) { - String instruction = arguments.split(ConfigConstant.CUSTOM_SPLIT)[0] + ChatConstant.BLANK; - String modelName = arguments.split(ConfigConstant.CUSTOM_SPLIT)[1]; - yield ConfigUtil.customModelChange(instruction, modelName); + if (arguments.matches(Constant.Order.MODEL_CHANGE)) { + //获取需更改的信息 + String[] argumentsArray = arguments.split(Constant.Order.SPLIT_CUSTOM); + String command = argumentsArray[0]; + int modelTemplateIndex = Integer.parseInt(argumentsArray[1]); + if (modelTemplateIndex >= Config.ConfigLoader.getConfig().getModelConfigTemplates().size()){ + yield "不存在模型模板["+modelTemplateIndex+"]"; + } + String customModel = argumentsArray[2]; + //迭代现有预设,更改对应信息 + for (CustomCommandTemplate customCommandTemplate : Config.ConfigLoader.getConfig().getCustomCommandTemplates()) { + if (customCommandTemplate.getCommand().equals(command)){ + customCommandTemplate.setModelTemplateIndex(modelTemplateIndex); + customCommandTemplate.setCustomModel(customModel); + yield "指令: "+command+"模型切换成功!\r\n"+customCommandTemplate; + } + } + yield "未找到指令: "+command; } else { - yield "格式不正确! 格式如下: \r\n" + ChatConstant.SET + "命令|预设指令|指令对应模型"; + yield "格式不正确!"; } } case "更改预设" -> { - if (arguments.matches(ConfigConstant.MODEL_CHANGE)) { - String instruction = arguments.split(ConfigConstant.CUSTOM_SPLIT)[0] + ChatConstant.BLANK; - String customContent = arguments.split(ConfigConstant.CUSTOM_SPLIT)[1]; - yield ConfigUtil.customContentChange(instruction, customContent); + if (arguments.matches(Constant.Order.MODEL_CHANGE)) { + String[] argumentsArray = arguments.split(Constant.Order.SPLIT_CUSTOM); + String command = argumentsArray[0]; + String customPromotion = argumentsArray[1]; + //迭代现有预设,更改对应信息 + for (CustomCommandTemplate customCommandTemplate : Config.ConfigLoader.getConfig().getCustomCommandTemplates()) { + if (customCommandTemplate.getCommand().equals(command)){ + customCommandTemplate.setCustomPromotion(customPromotion); + yield "指令: "+command+"更改预设成功!\r\n"+customCommandTemplate; + } + } + yield "未找到指令: "+command; } else { - yield "格式不正确! 格式如下: \r\n" + ChatConstant.SET + "命令|预设指令|指令对应预设"; + yield "格式不正确!"; } } - case "删除预设" -> ConfigUtil.removeCustom(arguments); + case "删除预设" -> Config.ConfigLoader.removeCustom(arguments); default -> "该指令不存在!"; }; } diff --git a/src/main/java/plugin/pojo/Config.java b/src/main/java/plugin/pojo/Config.java deleted file mode 100644 index 5a3c33a..0000000 --- a/src/main/java/plugin/pojo/Config.java +++ /dev/null @@ -1,226 +0,0 @@ -package plugin.pojo; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -public class Config { - /** - * 智谱apikey - */ - private String apikey; - - /** - * 阿里accessKey - */ - private String accessKeyId; - private String accessKeySecret; - - /** - * 基础配置 - */ - private String owner; - private String defaultModel; - private String bot; - private String timeout; - private String timeCheck; - private List blacklist; - - /** - * 自定义预设 - */ - private LinkedHashMap customCommands; - - public Config() { - } - - public Config(String apikey, String accessKeyId, String accessKeySecret, String owner, String defaultModel, String bot, String timeout, String timeCheck, LinkedHashMap customCommands) { - this.apikey = apikey; - this.accessKeyId = accessKeyId; - this.accessKeySecret = accessKeySecret; - this.owner = owner; - this.defaultModel = defaultModel; - this.bot = bot; - this.timeout = timeout; - this.timeCheck = timeCheck; - this.customCommands = customCommands; - } - - public Config(String apikey, String accessKeyId, String accessKeySecret, String owner, String defaultModel, String bot, String timeout, String timeCheck, List blacklist, LinkedHashMap customCommands) { - this.apikey = apikey; - this.accessKeyId = accessKeyId; - this.accessKeySecret = accessKeySecret; - this.owner = owner; - this.defaultModel = defaultModel; - this.bot = bot; - this.timeout = timeout; - this.timeCheck = timeCheck; - this.blacklist = blacklist; - this.customCommands = customCommands; - } - - /** - * 获取 - * @return apikey - */ - public String getApikey() { - return apikey; - } - - /** - * 设置 - * @param apikey - */ - public void setApikey(String apikey) { - this.apikey = apikey; - } - - /** - * 获取 - * @return accessKeyId - */ - public String getAccessKeyId() { - return accessKeyId; - } - - /** - * 设置 - * @param accessKeyId - */ - public void setAccessKeyId(String accessKeyId) { - this.accessKeyId = accessKeyId; - } - - /** - * 获取 - * @return accessKeySecret - */ - public String getAccessKeySecret() { - return accessKeySecret; - } - - /** - * 设置 - * @param accessKeySecret - */ - public void setAccessKeySecret(String accessKeySecret) { - this.accessKeySecret = accessKeySecret; - } - - /** - * 获取 - * @return owner - */ - public String getOwner() { - return owner; - } - - /** - * 设置 - * @param owner - */ - public void setOwner(String owner) { - this.owner = owner; - } - - /** - * 获取 - * @return modelNormal - */ - public String getDefaultModel() { - return defaultModel; - } - - /** - * 设置 - * @param defaultModel - */ - public void setDefaultModel(String defaultModel) { - this.defaultModel = defaultModel; - } - - /** - * 获取 - * @return bot - */ - public String getBot() { - return bot; - } - - /** - * 设置 - * @param bot - */ - public void setBot(String bot) { - this.bot = bot; - } - - /** - * 获取 - * @return timeout - */ - public String getTimeout() { - return timeout; - } - - /** - * 设置 - * @param timeout - */ - public void setTimeout(String timeout) { - this.timeout = timeout; - } - - /** - * 获取 - * @return timeCheck - */ - public String getTimeCheck() { - return timeCheck; - } - - /** - * 设置 - * @param timeCheck - */ - public void setTimeCheck(String timeCheck) { - this.timeCheck = timeCheck; - } - - /** - * 获取 - * @return customCommands - */ - public HashMap getCustomCommands() { - return customCommands; - } - - /** - * 设置 - * @param customCommands - */ - public void setCustomCommands(LinkedHashMap customCommands) { - this.customCommands = customCommands; - } - - @Override - public String toString() { - return "Config{apikey = " + apikey + ", accessKeyId = " + accessKeyId + ", accessKeySecret = " + accessKeySecret + ", owner = " + owner + ", modelNormal = " + defaultModel + ", modelCode = " + ", bot = " + bot + ", timeout = " + timeout + ", timeCheck = " + timeCheck + ", customCommands = " + customCommands + "}"; - } - - /** - * 获取 - * @return blacklist - */ - public List getBlacklist() { - return blacklist; - } - - /** - * 设置 - * @param blacklist - */ - public void setBlacklist(List blacklist) { - this.blacklist = blacklist; - } -} diff --git a/src/main/java/plugin/pojo/OCRDataInfo.java b/src/main/java/plugin/pojo/OCRDataInfo.java index ed0b4df..8981744 100644 --- a/src/main/java/plugin/pojo/OCRDataInfo.java +++ b/src/main/java/plugin/pojo/OCRDataInfo.java @@ -1,7 +1,12 @@ package plugin.pojo; +import lombok.Getter; +import lombok.Setter; + import java.util.List; +@Setter +@Getter public class OCRDataInfo { /** @@ -41,78 +46,6 @@ public class OCRDataInfo { */ private int width; - public String getAlgo_version() { - return algo_version; - } - - public void setAlgo_version(String algo_version) { - this.algo_version = algo_version; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public int getHeight() { - return height; - } - - public void setHeight(int height) { - this.height = height; - } - - public int getOrgHeight() { - return orgHeight; - } - - public void setOrgHeight(int orgHeight) { - this.orgHeight = orgHeight; - } - - public int getOrgWidth() { - return orgWidth; - } - - public void setOrgWidth(int orgWidth) { - this.orgWidth = orgWidth; - } - - public String getPrism_version() { - return prism_version; - } - - public void setPrism_version(String prism_version) { - this.prism_version = prism_version; - } - - public int getPrism_wnum() { - return prism_wnum; - } - - public void setPrism_wnum(int prism_wnum) { - this.prism_wnum = prism_wnum; - } - - public List getPrism_wordsInfo() { - return prism_wordsInfo; - } - - public void setPrism_wordsInfo(List prism_wordsInfo) { - this.prism_wordsInfo = prism_wordsInfo; - } - - public int getWidth() { - return width; - } - - public void setWidth(int width) { - this.width = width; - } - public static class PrismWordsInfoBean { /** * angle diff --git a/src/main/java/plugin/pojo/UserCustomLatestTime.java b/src/main/java/plugin/pojo/UserCustomLatestTime.java deleted file mode 100644 index 558e922..0000000 --- a/src/main/java/plugin/pojo/UserCustomLatestTime.java +++ /dev/null @@ -1,62 +0,0 @@ -package plugin.pojo; - -/** - * @author SLHAF - */ -public class UserCustomLatestTime { - private String chatCommand; - private Long latestTime; - - public UserCustomLatestTime() { - } - - public UserCustomLatestTime(String chatCommand, Long latestTime) { - this.chatCommand = chatCommand; - this.latestTime = latestTime; - } - - /** - * 获取 - * @return chatCommand - */ - public String getChatCommand() { - return chatCommand; - } - - /** - * 设置 - * @param chatCommand - */ - public void setChatCommand(String chatCommand) { - this.chatCommand = chatCommand; - } - - /** - * 获取 - * @return latestTime - */ - public Long getLatestTime() { - return latestTime; - } - - /** - * 设置 - * @param latestTime - */ - public void setLatestTime(Long latestTime) { - this.latestTime = latestTime; - } - - @Override - public String toString() { - return "UserCustomLatestTime{chatCommand = " + chatCommand + ", latestTime = " + latestTime + "}"; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof UserCustomLatestTime other) { - return other.getChatCommand().equals(this.chatCommand); - } - return super.equals(obj); - } -} diff --git a/src/main/java/plugin/pojo/UserCustomMessage.java b/src/main/java/plugin/pojo/UserCustomMessage.java deleted file mode 100644 index ecbfc64..0000000 --- a/src/main/java/plugin/pojo/UserCustomMessage.java +++ /dev/null @@ -1,57 +0,0 @@ -package plugin.pojo; - -import com.zhipu.oapi.service.v4.model.ChatMessage; - -import java.util.List; - -public class UserCustomMessage { - private String command; - private List messages; - - - public UserCustomMessage() { - } - - public UserCustomMessage(String command, List messages) { - this.command = command; - this.messages = messages; - } - - /** - * 获取 - * @return command - */ - public String getCommand() { - return command; - } - - /** - * 设置 - * @param command - */ - public void setCommand(String command) { - this.command = command; - } - - /** - * 获取 - * @return messages - */ - public List getMessages() { - return messages; - } - - /** - * 设置 - * @param messages - */ - public void setMessages(List messages) { - this.messages = messages; - } - - @Override - public String toString() { - return "UserCustomMessage{command = " + command + ", messages = " + messages + "}"; - } - -} diff --git a/src/main/java/plugin/utils/AIUtil.java b/src/main/java/plugin/utils/AIUtil.java deleted file mode 100644 index c4833d1..0000000 --- a/src/main/java/plugin/utils/AIUtil.java +++ /dev/null @@ -1,370 +0,0 @@ -package plugin.utils; - -import com.zhipu.oapi.ClientV4; -import com.zhipu.oapi.Constants; -import com.zhipu.oapi.service.v4.model.ChatCompletionRequest; -import com.zhipu.oapi.service.v4.model.ChatMessage; -import com.zhipu.oapi.service.v4.model.ChatMessageRole; -import com.zhipu.oapi.service.v4.model.ModelApiResponse; -import plugin.constant.AIConstant; -import plugin.constant.ChatConstant; -import plugin.constant.ConfigConstant; -import plugin.pojo.Config; -import plugin.pojo.UserCustomLatestTime; -import plugin.pojo.UserCustomMessage; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import static plugin.utils.ConfigUtil.logger; - - -/** - * @author SLHAF - */ -public class AIUtil { - private static final String APIKEY; - private static final ClientV4 CLIENT; - private static final String REQUEST_ID_TEMPLATE = "ChatAI_InGroup_v2"; - private static final HashMap> userDefaultMessages = new HashMap<>(); - private static final HashMap userLatestTimeOfDefault = new HashMap<>(); - private static String defaultModel; - - private static final HashMap> userCustomMessages = new HashMap<>(); - private static final HashMap> userLatestTimeOfCustom = new HashMap<>(); - /*private static String modelCode;*/ - /** - * 结构: - * /c : glm-4-flush|预设内容 - */ - private static HashMap customCommands; - - private static final Long CHECK_TIME, TIMEOUT; - - static { - Config config = ConfigUtil.getConfig(); - APIKEY = config.getApikey(); - CLIENT = new ClientV4.Builder(APIKEY).build(); - defaultModel = config.getDefaultModel(); - customCommands = config.getCustomCommands(); - CHECK_TIME = Long.valueOf(config.getTimeCheck().substring(1)); - TIMEOUT = Long.valueOf(config.getTimeout().substring(1)); - new Thread(() -> { - while (true) { - try { - Thread.sleep(CHECK_TIME); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - if (!userLatestTimeOfDefault.isEmpty()) { - //查看user最近时间,如果超过TIMEOUT,则清理对应记录 - userLatestTimeOfDefault.forEach((id, latestTime) -> { - synchronized (userDefaultMessages.get(id)) { - Long currentTime = System.currentTimeMillis(); - if (currentTime - latestTime > TIMEOUT && userDefaultMessages.containsKey(id)) { - userDefaultMessages.remove(id); - logger.info("default记录清理:" + id); - } - } - }); - } - - - if (!userLatestTimeOfCustom.isEmpty()) { - //查看user最近时间,如果超过TIMEOUT,则清理对应记录 - userLatestTimeOfCustom.forEach((id, userCustomLatestTimeList) -> { - synchronized (userCustomMessages.get(id)) { - ArrayList indexToRemove = new ArrayList<>(); - Long currentTime = System.currentTimeMillis(); - for (int i = 0; i < userCustomLatestTimeList.size(); i++) { - if (currentTime - userCustomLatestTimeList.get(i).getLatestTime() > TIMEOUT){ - logger.info("custom记录清理: "+id+" "+userCustomLatestTimeList.get(i).getChatCommand()); - userCustomMessages.get(id).remove(i); - indexToRemove.add(i); - } - } - //移除最近操作时间 - for (int i : indexToRemove) { - userCustomLatestTimeList.remove(i); - } - } - }); - } - - } - }).start(); - logger.info("清理线程启动"); - logger.info("当前默认聊天模型: " + defaultModel); - } - - private AIUtil() { - } - - public static String customChat(Long id, String content, String url, String chatCommand) { - if (ChatConstant.CLEAR.equals(content.replace(ChatConstant.BLANK, ""))) { - if (!userCustomMessages.containsKey(id)) { - return "不存在消息记录"; - } - ArrayList indexToRemove = new ArrayList<>(); - List userCustomMessageList = userCustomMessages.get(id); - for (int i = 0; i < userCustomMessageList.size(); i++) { - if (userCustomMessageList.get(i).getCommand().equals(chatCommand)) { - indexToRemove.add(i); - } - } - indexToRemove.forEach(i -> userCustomMessageList.remove(i.intValue())); - return "消息记录已清空"; - } else if (AIConstant.CURRENT_MODEL.equals(content.replace(ChatConstant.BLANK, ""))) { - String modelName = customCommands.get(chatCommand).split(ConfigConstant.CUSTOM_SPLIT)[0]; - return "当前模型为: " + modelName; - } - //查看本次id是否有记录存在 - if (!userCustomMessages.containsKey(id)) { - //不存在消息记录 - //创建消息list - List chatMessages = new ArrayList<>(); - if (!customCommands.get(chatCommand).split(ConfigConstant.CUSTOM_SPLIT)[1].equals(ConfigConstant.NULL)) { - ChatMessage customMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), customCommands.get(chatCommand).split(ConfigConstant.CUSTOM_SPLIT)[1]); - chatMessages.add(customMessage); - } - List userCustomMessageList = new ArrayList<>(); - userCustomMessageList.add(new UserCustomMessage(chatCommand, chatMessages)); - userCustomMessages.put(id, userCustomMessageList); - }else { - //存在消息记录,但需要判断是否存在该指令对应的消息记录 - List userCustomMessageList = userCustomMessages.get(id); - boolean found = false; - for (UserCustomMessage userCustomMessage : userCustomMessageList) { - if (userCustomMessage.getCommand().equals(chatCommand)) { - found = true; - break; - } - } - if (!found) { - //如果不存在该指令对应的消息记录 - UserCustomMessage userCustomMessage = new UserCustomMessage(); - userCustomMessage.setCommand(chatCommand); - List chatMessages = new ArrayList<>(); - //判断是否存在预设 - if (!customCommands.get(chatCommand).split(ConfigConstant.CUSTOM_SPLIT)[1].equals(ConfigConstant.NULL)){ - ChatMessage customMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), customCommands.get(chatCommand).split(ConfigConstant.CUSTOM_SPLIT)[1]); - chatMessages.add(customMessage); - } - userCustomMessage.setMessages(chatMessages); - userCustomMessageList.add(userCustomMessage); - } - } - String modelName = customCommands.get(chatCommand).split(ConfigConstant.CUSTOM_SPLIT)[0]; - synchronized (userCustomMessages.get(id)) { - return getChatResponse(id, content, url, modelName, chatCommand); - } - } - - public static String defaultChat(Long id, String content, String url) { - if (ChatConstant.CLEAR.equals(content.replace(ChatConstant.BLANK, ""))) { - if (!userDefaultMessages.containsKey(id)) { - return "不存在消息记录"; - } - userDefaultMessages.remove(id); - return "消息记录已清空"; - } else if (ChatConstant.CURRENT_MODEL.equals(content.replace(ChatConstant.BLANK, ""))) { - return "当前模型为: " + defaultModel; - } - //查看本次id是否有记录存在 - if (!userDefaultMessages.containsKey(id)) { - //创建消息list - List chatMessages = new ArrayList<>(); - if (customCommands.containsKey(ConfigConstant.DEFAULT+ChatConstant.BLANK) && !ConfigConstant.NULL.equals(customCommands.get(ConfigConstant.DEFAULT+ChatConstant.BLANK))) { - ChatMessage customMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), customCommands.get(ConfigConstant.DEFAULT+ChatConstant.BLANK)); - chatMessages.add(customMessage); - } - userDefaultMessages.put(id, chatMessages); - } - synchronized (userDefaultMessages.get(id)) { - return getChatResponse(id, content, url, defaultModel, null); - } - } - - public static String chatOnce(String content, String url) { - - if (AIConstant.CURRENT_MODEL.equals(content.replace(ChatConstant.BLANK, ""))) { - return "当前模型为: " + defaultModel; - } - String result = ""; - if (url != null) { - if (!OCRUtil.isSupported) { - return "当前不支持文字识别,请检查阿里云OCR相关配置。"; - } else { - String contentOfImage = OCRUtil.getContentOfImage(url); - if (contentOfImage == null) { - result = "未识别出图片内容。"; - } else if (AIConstant.ERROR.equals(contentOfImage)) { - result = "识别图片内容出错,请查看控制台。"; - } else { - content = content.replace("[图片]", "\r\n[" + contentOfImage + "]\r\n"); - } - } - } - String requestId = REQUEST_ID_TEMPLATE + "_once_" + System.currentTimeMillis(); - List messages = new ArrayList<>(); - messages.add(new ChatMessage(ChatMessageRole.USER.value(), content)); - ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() - .model(defaultModel) - .stream(Boolean.FALSE) - .invokeMethod(Constants.invokeMethod) - .messages(messages) - .requestId(requestId) - .build(); - ModelApiResponse invokeModelApiResp = CLIENT.invokeModelApi(chatCompletionRequest); - int code = invokeModelApiResp.getCode(); - if (code == AIConstant.NORMAL_CODE) { - printTokenInfo(invokeModelApiResp); - return invokeModelApiResp.getData().getChoices().get(0).getMessage().getContent().toString(); - } else { - logger.warning("code: " + code); - logger.warning("ErrorCode:" + invokeModelApiResp.getData().getError().getCode()); - logger.warning("msg:" + invokeModelApiResp.getData().getError().getMessage()); - return invokeModelApiResp.getMsg() + "\r\n<" + result + ">"; - } - } - - - /** - * 取得回复内容 - *
chatMessages内容只有两个static变量,只需根据传入的chatCommand是否为null进行判断 - * - * @param id 聊天用户ID - * @param content 聊天用户发送的内容,content已在Listener处进行处理 - * @param url 获取到的图片url,如果没有图片,则为null - * @param model 本次对话所需的模型名称 - *
当为userDefaultMessages时: - *
- *
qq1 : [msg1,msg2,msg3] - *
qq2 : [msg1,msg2,msg3] - *
- *
当为userCustomMessages时: - *
- *
qq1 : [{command1,[msg1.msg2,msg3]},{command2,[msg1,msg2,msg3]},{command3,[msg1,msg2,msg3]}] - *
qq2 : [{command1,[msg1.msg2,msg3]},{command2,[msg1,msg2,msg3]},{command3,[msg1,msg2,msg3]}] - *
- * @param chatCommand 聊天指令 - * @return 得到的模型响应内容 - */ - private static String getChatResponse(Long id, String content, String url, String model, String chatCommand) { - String requestId = REQUEST_ID_TEMPLATE + "_" + model + "_" + System.currentTimeMillis(); - //处理url内容 - String result = ""; - if (url != null) { - if (!OCRUtil.isSupported) { - logger.warning("unSupportedOCR"); - return "当前不支持文字识别,请检查阿里云OCR相关配置。"; - } else { - String contentOfImage = OCRUtil.getContentOfImage(url); - if (contentOfImage == null) { - result = "未识别出图片内容。"; - } else if (AIConstant.ERROR.equals(contentOfImage)) { - result = "识别图片内容出错,请查看控制台。"; - } else { - content = content.replace("[图片]", "\r\n[" + contentOfImage + "]\r\n"); - } - } - } - logger.info("final content:" + content); - - //根据primaryUserMessages中的内容来定义userMessages并更新latestTime - List chatMessages = null; - if (chatCommand == null) { - chatMessages = userDefaultMessages.get(id); - userLatestTimeOfDefault.put(id, System.currentTimeMillis()); - } else { - List userCustomMessageList = userCustomMessages.get(id); - for (UserCustomMessage userCustomMessage : userCustomMessageList) { - //在调用时已确保存在指令对应的消息记录 - if (userCustomMessage.getCommand().equals(chatCommand)) { - chatMessages = userCustomMessage.getMessages(); - break; - } - } - //更新最新操作时间 - boolean foundTime = false; - List userCustomLatestTimeList; - if (userLatestTimeOfCustom.containsKey(id)) { - //如果存在该id对应的任一聊天记录 - userCustomLatestTimeList = userLatestTimeOfCustom.get(id); - for (UserCustomLatestTime userCustomLatestTime : userCustomLatestTimeList) { - if (userCustomLatestTime.getChatCommand().equals(chatCommand)) { - userCustomLatestTime.setLatestTime(System.currentTimeMillis()); - foundTime = true; - break; - } - } - }else { - //如果没有记录存在 - userCustomLatestTimeList = new ArrayList<>(); - userCustomLatestTimeList.add(new UserCustomLatestTime(chatCommand,System.currentTimeMillis())); - userLatestTimeOfCustom.put(id,userCustomLatestTimeList); - foundTime = true; - } - if (!foundTime) { - userCustomLatestTimeList.add(new UserCustomLatestTime(chatCommand, System.currentTimeMillis())); - } - } - - if (chatMessages == null) { - return "消息记录读取失败"; - } - - //添加消息 - chatMessages.add(new ChatMessage(ChatMessageRole.USER.value(), content)); - - //创建并发送请求 - ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() - .model(model) - .stream(Boolean.FALSE) - .invokeMethod(Constants.invokeMethod) - .messages(chatMessages) - .requestId(requestId).build(); - - ModelApiResponse invokeModelApiResp = CLIENT.invokeModelApi(chatCompletionRequest); - int code = invokeModelApiResp.getCode(); - if (code == AIConstant.NORMAL_CODE) { - printTokenInfo(invokeModelApiResp); - String response = invokeModelApiResp.getData().getChoices().get(0).getMessage().getContent().toString(); - chatMessages.add(new ChatMessage(ChatMessageRole.ASSISTANT.value(), response)); - return response; - } else { - logger.warning("code: " + code); - logger.warning("ErrorCode:" + invokeModelApiResp.getData().getError().getCode()); - logger.warning("msg:" + invokeModelApiResp.getData().getError().getMessage()); - return invokeModelApiResp.getMsg() + "\r\n<" + result + ">"; - } - } - - private static void printTokenInfo(ModelApiResponse invokeModelApiResp) { - int promptTokens = invokeModelApiResp.getData().getUsage().getPromptTokens(); - int completionTokens = invokeModelApiResp.getData().getUsage().getCompletionTokens(); - int totalTokens = invokeModelApiResp.getData().getUsage().getTotalTokens(); - logger.info("prompt_tokens: " + promptTokens); - logger.info("completion_tokens: " + completionTokens); - logger.info("total_tokens: " + totalTokens); - } - - /** - * 清空所有聊天记录 - */ - public static String clearAll() { - int size = 0; - size += userDefaultMessages.size(); - userDefaultMessages.clear(); - userLatestTimeOfDefault.clear(); - - for (Long id : userCustomMessages.keySet()) { - size += userCustomMessages.get(id).size(); - } - userCustomMessages.clear(); - userLatestTimeOfCustom.clear(); - return "本次清空" + size + "条会话"; - } -} diff --git a/src/main/java/plugin/utils/ChatUtil.java b/src/main/java/plugin/utils/ChatUtil.java new file mode 100644 index 0000000..57a6009 --- /dev/null +++ b/src/main/java/plugin/utils/ChatUtil.java @@ -0,0 +1,110 @@ +package plugin.utils; + +import lombok.extern.slf4j.Slf4j; +import plugin.chat.ChatClient; +import plugin.chat.constant.Constant; +import plugin.chat.pojo.ChatResponse; +import plugin.config.Config; +import plugin.config.CustomCommandTemplate; +import plugin.config.ModelConfigTemplate; + +import java.util.HashMap; +import java.util.Objects; + +@Slf4j +public class ChatUtil { + + private static final HashMap chatClients = new HashMap<>(); + private static final HashMap latestTime = new HashMap<>(); + + private ChatUtil() { + + } + + static { + launchCleanerThread(); + } + + private static void launchCleanerThread() { + Config config = Config.ConfigLoader.getConfig(); + long timeout = Long.parseLong(config.getTimeout()); + long timeCheck = Long.parseLong(config.getTimeCheck()); + Thread thread = new Thread(() -> { + long currentTime = System.currentTimeMillis(); + while (true) { + synchronized (chatClients) { + latestTime.forEach((chatId, latestTime) -> { + if (currentTime - latestTime > timeout) { + chatClients.remove(chatId); + log.info("记录清理: {}", chatId); + } + }); + } + try { + Thread.sleep(timeCheck); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + }); + thread.setName("ChatClientsCleaner"); + thread.start(); + } + + public static String chat(String id, String content, String command) { + String chatId = id + "-" + command; + ChatResponse chatResponse = null; + synchronized (chatClients) { + if (chatClients.containsKey(chatId)) { + ChatClient chatClient = chatClients.get(chatId); + chatResponse = chatClient.runChat(content); + } else { + int modelTemplateIndex; + String customModel; + String customPromotion; + + Config config = Config.ConfigLoader.getConfig(); + for (CustomCommandTemplate customCommandTemplate : config.getCustomCommandTemplates()) { + if (customCommandTemplate.getCommand().equals(command)) { + modelTemplateIndex = customCommandTemplate.getModelTemplateIndex(); + customModel = customCommandTemplate.getCustomModel(); + customPromotion = customCommandTemplate.getCustomPromotion(); + ModelConfigTemplate modelConfigTemplate = config.getModelConfigTemplates().get(modelTemplateIndex); + String url = modelConfigTemplate.getBase_url(); + String apikey = modelConfigTemplate.getApikey(); + + ChatClient chatClient = new ChatClient(chatId, url, apikey, customModel); + chatClient.setPromotion(customPromotion); + chatClients.put(chatId, chatClient); + chatResponse = chatClient.runChat(content); + } + } + } + if (Objects.requireNonNull(chatResponse).getType().equals(Constant.Response.ERROR)) { + log.warn("出现错误: {}", chatResponse.getMessage()); + return "ERROR!\r\n" + chatResponse.getMessage(); + } + log.info("本次消耗Token: {}", Objects.requireNonNull(chatResponse).getUsageBean().toString()); + latestTime.put(chatId, System.currentTimeMillis()); + } + return chatResponse.getMessage(); + } + + public static String removeClient(String id,String command) { + String chatId = id + "-" + command; + synchronized (chatClients) { + chatClients.remove(chatId); + latestTime.remove(chatId); + } + return "消息记录: "+chatId +"已清空"; + } + + public static String removeAllClients(){ + synchronized (chatClients) { + chatClients.clear(); + latestTime.clear(); + } + return "所有消息记录已清空"; + } +} diff --git a/src/main/java/plugin/utils/ConfigUtil.java b/src/main/java/plugin/utils/ConfigUtil.java deleted file mode 100644 index a683853..0000000 --- a/src/main/java/plugin/utils/ConfigUtil.java +++ /dev/null @@ -1,199 +0,0 @@ -package plugin.utils; - -import cn.hutool.core.bean.BeanUtil; -import net.mamoe.mirai.utils.LoggerAdapters; -import net.mamoe.mirai.utils.MiraiLogger; -import org.slf4j.Logger; -import org.yaml.snakeyaml.DumperOptions; -import org.yaml.snakeyaml.Yaml; -import plugin.constant.ChatConstant; -import plugin.constant.ConfigConstant; -import plugin.pojo.Config; - -import java.io.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; - - -/** - * @author SLHAF - */ -public class ConfigUtil { - private static final String CONFIG_PATH = "./config/ChatAIinGroup/config.yaml"; - private static final Yaml yaml; - private static Config config; - private static final Logger log = org. slf4j. LoggerFactory. getLogger("ChatAIinGroup"); - public static MiraiLogger logger = LoggerAdapters.asMiraiLogger(log);; - - private ConfigUtil() { - } - - static { - DumperOptions options = new DumperOptions(); - options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); - yaml = new Yaml(options); - config = new Config(); - } - - /** - * 检查配置 - * - * @throws IOException 配置文件写入出错 - */ - public static void load() throws IOException, ClassNotFoundException { - //检查配置文件 - File file = new File(CONFIG_PATH); - if (!file.exists()) { - //创建配置文件 - file.getParentFile().mkdirs(); - file.createNewFile(); - config.setApikey("your_zhipu_apikey"); - config.setAccessKeyId("your_ali_access_key_id"); - config.setAccessKeySecret("your_ali_access_key_secret"); - config.setOwner("your_bot_owner_qq_number(e.g. Q1145141919810)"); - config.setDefaultModel("glm-4-flash"); - config.setBot("your_bot_qq_number(e.g. Q1145141919810)"); - config.setTimeout("M3600000"); - config.setTimeCheck("M60000"); - ArrayList blacklist = new ArrayList<>(); - blacklist.add(123456789L); - blacklist.add(987654321L); - config.setBlacklist(blacklist); - LinkedHashMap commands = new LinkedHashMap<>(); - commands.put("default ", "null"); - commands.put("/c ", "glm-4-flash|你是一位智能编程助手,你会为用户回答关于编程、代码、计算机方面的任何问题,并提供格式规范、可以执行、准确安全的代码,并在必要时提供详细的解释。 请用中文回答。"); - config.setCustomCommands(commands); - dump(); - logger.warning("配置文件创建成功,请关闭后进行配置"); - System.exit(0); - } else { - //读取配置文件 - InputStream inputStream = new FileInputStream(CONFIG_PATH); - config = BeanUtil.toBean(yaml.load(new FileInputStream(CONFIG_PATH)), Config.class); - inputStream.close(); - logger.info(config.toString()); - logger.info("读取配置文件完毕"); - HashMap customCommands = config.getCustomCommands(); - if (!customCommands.containsKey(ConfigConstant.DEFAULT+ChatConstant.BLANK)){ - logger.warning("未找到default预设!"); - customCommands.put("default ","null"); - dump(); - logger.warning("已自动添加default预设!"); - } - Class.forName("plugin.utils.AIUtil"); - Class.forName("plugin.utils.OCRUtil"); - } - } - - public static Config getConfig() { - return config; - } - - - public static String customModelChange(String instruction, String customModel) throws IOException { - HashMap customCommands = config.getCustomCommands(); - synchronized (customCommands) { - if (!customCommands.containsKey(instruction)) { - return "该预设不存在!"; - } - if ((ConfigConstant.DEFAULT+ChatConstant.BLANK).equals(instruction)){ - config.setDefaultModel(customModel); - dump(); - return "模型切换成功: [defaultModel -> "+config.getDefaultModel()+"]"; - }else { - String customContent = customCommands.get(instruction).split(ConfigConstant.CUSTOM_SPLIT)[1]; - customCommands.put(instruction, customModel + "|" + customContent); - dump(); - return "模型切换成功: [" + instruction + "->" + customCommands.get(instruction) + "]"; - } - } - } - - private static void dump() throws IOException { - FileWriter writer = new FileWriter(CONFIG_PATH); - yaml.dump(BeanUtil.beanToMap(config), writer); - } - - /** - * 关闭当前群聊发言 - * - * @param id 群聊id - */ - public static String shutUp(long id) { - config.getBlacklist().add(id); - return "ChatAI-InGroup 已关闭"; - } - - /** - * 开启当前群聊发言 - * - * @param id 群聊id - */ - public static String speak(long id) { - config.getBlacklist().remove(id); - return "ChatAI-InGroup 已开启"; - } - - /** - * 添加预设 - * - * @param instruction 指令 - * @param customModel 预设模型 - * @param customContent 预设内容 - * @return 运行结果 - * @throws IOException 配置保存出错 - */ - public static String addCustom(String instruction, String customModel, String customContent) throws IOException { - HashMap customCommands = config.getCustomCommands(); - synchronized (customCommands) { - if (customCommands.containsKey(instruction)) { - return "已存在当前指令! \r\n[" + instruction + "->" + customCommands.get(instruction) + "]"; - } - String content = customModel + "|" + customContent; - customCommands.put(instruction, content); - dump(); - return "预设添加完毕! \r\n[" + instruction + "->" + content + "]"; - } - } - - /** - * 改变指令对应预设 - * - * @param instruction 指令 - * @param customContent 预设内容 - * @return 运行结果 - */ - public static String customContentChange(String instruction, String customContent) throws IOException { - HashMap customCommands = config.getCustomCommands(); - synchronized (customCommands) { - if (!customCommands.containsKey(instruction)) { - return "该指令不存在!"; - } - if ((ConfigConstant.DEFAULT+ChatConstant.BLANK).equals(instruction)) { - customCommands.put(instruction, customContent); - }else { - String modelName = customCommands.get(instruction).split(ConfigConstant.CUSTOM_SPLIT)[0]; - customCommands.put(instruction, modelName + "|" + customContent); - } - dump(); - return "预设更改成功! \r\n[" + instruction + "->" + customCommands.get(instruction) + "]"; - } - } - - public static String removeCustom(String arguments) throws IOException { - HashMap customCommands = getConfig().getCustomCommands(); - synchronized (customCommands) { - if (!customCommands.containsKey(arguments + ChatConstant.BLANK)) { - return "该预设不存在"; - } - if (ConfigConstant.DEFAULT.equals(arguments)){ - return "默认配置不可删除!"; - } - String content = customCommands.get(arguments + ChatConstant.BLANK); - customCommands.remove(arguments + ChatConstant.BLANK); - dump(); - return "删除预设[" + arguments + "->" + content + "]成功"; - } - } -} diff --git a/src/main/java/plugin/utils/OCRUtil.java b/src/main/java/plugin/utils/OCRUtil.java index 313f164..d97dec1 100644 --- a/src/main/java/plugin/utils/OCRUtil.java +++ b/src/main/java/plugin/utils/OCRUtil.java @@ -6,24 +6,23 @@ import com.aliyun.ocr_api20210707.models.RecognizeAdvancedRequest; import com.aliyun.ocr_api20210707.models.RecognizeAdvancedResponse; import com.aliyun.tea.TeaException; import com.aliyun.teautil.models.RuntimeOptions; -import plugin.pojo.Config; +import lombok.extern.slf4j.Slf4j; +import plugin.config.Config; import plugin.pojo.OCRDataInfo; -import static plugin.utils.ConfigUtil.logger; - - +@Slf4j public class OCRUtil { private static Client client; public static boolean isSupported; static { //读取密钥 - Config pluginConfig = ConfigUtil.getConfig(); - String accessKeyId = pluginConfig.getAccessKeyId(); - String accessKeySecret = pluginConfig.getAccessKeySecret(); + Config pluginConfig = Config.ConfigLoader.getConfig(); + String accessKeyId = pluginConfig.getOcrConfig().getAccessKeyId(); + String accessKeySecret = pluginConfig.getOcrConfig().getAccessKeySecret(); if (accessKeySecret == null || accessKeyId == null) { isSupported = false; - logger.warning("未检测到阿里云OCR配置信息,图片文字识别将不可用。"); + log.warn("未检测到阿里云OCR配置信息,图片文字识别将不可用。"); } else { isSupported = true; com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() @@ -33,10 +32,10 @@ public class OCRUtil { try { client = new Client(config); } catch (Exception e) { - logger.error("创建client出错"); - logger.error(e.getMessage()); + log.error("创建client出错"); + log.error(e.getMessage()); } - logger.info("阿里云OCR已配置。"); + log.info("阿里云OCR已配置。"); } } @@ -65,18 +64,18 @@ public class OCRUtil { } catch (TeaException error) { // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 // 错误 message - logger.error(error.getMessage()); + log.error(error.getMessage()); // 诊断地址 - logger.error(error.getData().get("Recommend").toString()); + log.error(error.getData().get("Recommend").toString()); com.aliyun.teautil.Common.assertAsString(error.message); return "ERROR"; } catch (Exception _error) { TeaException error = new TeaException(_error.getMessage(), _error); // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 // 错误 message - logger.error(error.getMessage()); + log.error(error.getMessage()); // 诊断地址 - logger.error(error.getData().get("Recommend").toString()); + log.error(error.getData().get("Recommend").toString()); com.aliyun.teautil.Common.assertAsString(error.message); return "ERROR"; } diff --git a/src/test/java/MyTest.java b/src/test/java/MyTest.java index d2bc1b6..0926fa1 100644 --- a/src/test/java/MyTest.java +++ b/src/test/java/MyTest.java @@ -14,19 +14,10 @@ import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; import org.junit.Test; import plugin.App; -import plugin.constant.ChatConstant; -import plugin.constant.ConfigConstant; -import plugin.listener.OwnerMessageListener; -import plugin.utils.AIUtil; -import plugin.utils.ConfigUtil; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.Scanner; -import static kotlin.io.ConsoleKt.readln; - public class MyTest { @Test @@ -128,57 +119,6 @@ public class MyTest { client.close(); } - @Test - public void ownerTest() throws ClassNotFoundException, IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException { - ConfigUtil.load(); - - Class clazz = OwnerMessageListener.class; - Method handleCommand = clazz.getDeclaredMethod("handleCommand", String.class, String.class); - handleCommand.setAccessible(true); - while (true){ - String input = readln(); - String command = input.split(ChatConstant.BLANK)[0]; - String arguments = input.split(ChatConstant.BLANK)[1]; - - Object invoke = handleCommand.invoke(clazz.getDeclaredConstructor().newInstance(), command, arguments); - System.out.println(invoke); - } - - } - - @Test - public void chatTest() throws IOException, ClassNotFoundException { - ConfigUtil.load(); - - Long id = 1L; - String content = "你好"; - String chatCommand = "/c "; - - String customChat = AIUtil.customChat(id, content, null, chatCommand); - System.out.println(customChat); - - String defaultChat = AIUtil.defaultChat(id, content, null); - System.out.println(defaultChat); - - String chatOnce = AIUtil.chatOnce(content, null); - System.out.println(chatOnce); - } - - @Test - public void regexTest(){ - String str = "/c glm"; - System.out.println(str.matches(ConfigConstant.MODEL_CHANGE)); - } - - @Test - public void textBlockTest(){ - String str = """ - aliyun: - 123: - 111 - """; - System.out.println(str); - } @Test public void terminalTest() throws InterruptedException {