修改为OpenAI规范

去除了单次对话
配置文件格式修改
待测试
This commit is contained in:
2024-12-07 15:08:56 +08:00
parent d8932aba5c
commit dba16e99c2
28 changed files with 827 additions and 1269 deletions

View File

@@ -20,6 +20,7 @@ dependencies{
implementation ("org.apache.logging.log4j:log4j-api:2.23.1") implementation ("org.apache.logging.log4j:log4j-api:2.23.1")
implementation("top.mrxiaom.mirai:overflow-core-api:1.0.0.519-0d68f08-SNAPSHOT") implementation("top.mrxiaom.mirai:overflow-core-api:1.0.0.519-0d68f08-SNAPSHOT")
implementation ("com.alibaba:fastjson:1.2.73") implementation ("com.alibaba:fastjson:1.2.73")
implementation ("org.projectlombok:lombok:1.18.36")
} }

View File

@@ -6,16 +6,15 @@ import net.mamoe.mirai.event.GlobalEventChannel;
import net.mamoe.mirai.event.events.FriendMessageEvent; import net.mamoe.mirai.event.events.FriendMessageEvent;
import net.mamoe.mirai.event.events.GroupMessageEvent; import net.mamoe.mirai.event.events.GroupMessageEvent;
import net.mamoe.mirai.event.events.MessageEvent; import net.mamoe.mirai.event.events.MessageEvent;
import plugin.constant.ChatConstant; import plugin.chat.constant.Constant;
import plugin.constant.Constant; import plugin.config.Config;
import plugin.config.CustomCommandTemplate;
import plugin.listener.FriendMessageListener; import plugin.listener.FriendMessageListener;
import plugin.listener.GroupMessageListener; import plugin.listener.GroupMessageListener;
import plugin.listener.OwnerMessageListener; import plugin.listener.OwnerMessageListener;
import plugin.pojo.Config;
import plugin.utils.ConfigUtil;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -36,28 +35,30 @@ public final class App extends JavaPlugin {
@Override @Override
public void onEnable() { public void onEnable() {
String owner, bot; String owner, bot;
HashMap<String, String> customCommands; ArrayList<CustomCommandTemplate> customCommands;
List<Long> blacklist; List<Long> blacklist;
//加载配置 //加载配置
try { try {
ConfigUtil.load(); Config config = Config.ConfigLoader.load();
Thread.sleep(1500); App.class.getClassLoader().loadClass("plugin.utils.OCRUtil");
Config config = ConfigUtil.getConfig(); App.class.getClassLoader().loadClass("plugin.utils.ChatUtil");
owner = config.getOwner().substring(1); owner = config.getOwner().substring(1);
bot = config.getBot().substring(1); bot = config.getBot().substring(1);
customCommands = config.getCustomCommands(); customCommands = config.getCustomCommandTemplates();
blacklist = config.getBlacklist(); blacklist = config.getBlacklist();
} catch (IOException | ClassNotFoundException | InterruptedException e) { } catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
getLogger().info("ChatAI-InGroup loaded!"); getLogger().info("ChatAI loaded!");
//群聊监听器 //群聊监听器
GlobalEventChannel.INSTANCE.filterIsInstance(GroupMessageEvent.class) GlobalEventChannel.INSTANCE.filterIsInstance(GroupMessageEvent.class)
.filter(event -> { .filter(event -> {
String msg = event.getMessage().contentToString(); String msg = event.getMessage().contentToString();
long groupId = event.getGroup().getId(); 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()); }).registerListenerHost(new GroupMessageListener());
//私聊监听器 //私聊监听器
@@ -65,7 +66,10 @@ public final class App extends JavaPlugin {
.filter(event -> { .filter(event -> {
String msg = event.getMessage().contentToString(); String msg = event.getMessage().contentToString();
String sender = String.valueOf(event.getFriend().getId()); 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()); }).registerListenerHost(new FriendMessageListener());
//所有者监听 //所有者监听
@@ -97,23 +101,39 @@ public final class App extends JavaPlugin {
$ clearAll (仅限群聊) $ clearAll (仅限群聊)
$ shutUp (仅限群聊) $ shutUp (仅限群聊)
$ speak (仅限群聊) $ speak (仅限群聊)
$ 添加预设|<预设指令>|<模型名称/null>|<预设内容> $ 添加预设|<预设指令>|<模型模板ID>|<模型名称>|<预设内容>
$ 切换模型|<预设指令>|<模型名称> $ 切换模型|<预设指令>|<模型模板ID>|<模型名称>
$ 更改预设|<预设指令>|<预设内容> $ 更改预设|<预设指令>|<预设内容>
$ 删除预设|<预设指令> $ 删除预设|<预设指令>
例: 例:
$ 添加预设|/c|glm-4-flash|你是一只猫娘... $ 添加预设|/c|<模型模板ID>|glm-4-flash|你是一只猫娘...
"""}; """};
helpMsg[0] += "————<预设列表>————"; 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]); event.getSubject().sendMessage(helpMsg[0]);
} }
}); });
} }
private boolean checkCommandExist(String prefix, ArrayList<CustomCommandTemplate> customCommands) {
for (CustomCommandTemplate customCommand : customCommands) {
if (customCommand.getCommand().equals(prefix)) {
return true;
}
}
return false;
}
@Override @Override
public void onDisable() { public void onDisable() {
getLogger().info("ChatAI-InGroup disabled!"); getLogger().info("ChatAI-InGroup disabled!");

View File

@@ -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<Message> 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;
}
}

View File

@@ -1,4 +1,4 @@
package plugin.constant; package plugin.chat.constant;
public class Constant { public class Constant {
public static class Character{ public static class Character{
@@ -42,9 +42,21 @@ public class Constant {
public static final String DEFAULT = "default"; public static final String DEFAULT = "default";
public static final String NULL = "null"; 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 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";
} }
} }

View File

@@ -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<Message> 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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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<ChoicesBean> 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;
}
}
}

View File

@@ -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 + "}";
}
}

View File

@@ -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<Long> blacklist;
/**
* 阿里OCR配置
*/
private AliOCRConfig ocrConfig;
/**
* 模板配置
*/
private List<ModelConfigTemplate> modelConfigTemplates;
/**
* 预设配置
*/
private ArrayList<CustomCommandTemplate> 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<Long> blacklist = new ArrayList<>();
blacklist.add(123456789L);
blacklist.add(987654321L);
config.setBlacklist(blacklist);
//OCR配置
config.setOcrConfig(new AliOCRConfig("ocr_accessKeyId", "ocr_accessKeySecret"));
//模型模板
List<ModelConfigTemplate> 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<CustomCommandTemplate> 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<CustomCommandTemplate> 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<CustomCommandTemplate> 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);
}
}
}

View File

@@ -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";
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -1,46 +0,0 @@
package plugin.constant;
/**
* @author SLHAF
*/
public class ChatConstant {
/**
* 匹配含有图片信息的消息
*/
public static final String MATCH_MESSAGE = ".*[mirai:image:(https?://[\\w./?&amp;=]+)].*";
/**
* 匹配图片信息
*/
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";
}

View File

@@ -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 = ".*\\|.*";
}

View File

@@ -6,16 +6,10 @@ public enum MethodsConstant {
* 正常对话 * 正常对话
*/ */
NORMAL, NORMAL,
/**
* 单次对话
*/
ONCE,
/** /**
* 预设对话 * 预设对话
*/ */
CUSTOM, CUSTOM,
/** /**
* 未匹配 * 未匹配
*/ */

View File

@@ -3,10 +3,9 @@ package plugin.listener;
import net.mamoe.mirai.event.EventHandler; import net.mamoe.mirai.event.EventHandler;
import net.mamoe.mirai.event.SimpleListenerHost; import net.mamoe.mirai.event.SimpleListenerHost;
import net.mamoe.mirai.event.events.FriendMessageEvent; import net.mamoe.mirai.event.events.FriendMessageEvent;
import plugin.constant.ChatConstant; import plugin.chat.constant.Constant;
import plugin.constant.MethodsConstant; import plugin.utils.ChatUtil;
import plugin.utils.AIUtil; import plugin.utils.OCRUtil;
import plugin.utils.ConfigUtil;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -22,9 +21,9 @@ public class FriendMessageListener extends SimpleListenerHost {
String content = event.getMessage().contentToString(); String content = event.getMessage().contentToString();
String miraiCode = event.getMessage().serializeToMiraiCode(); String miraiCode = event.getMessage().serializeToMiraiCode();
String url = null; String url = null;
String chatCommand = null; String chatCommand;
if (miraiCode.matches(ChatConstant.MATCH_MESSAGE)) { if (miraiCode.matches(Constant.Regex.MATCH_MESSAGE)) {
String regex = ChatConstant.MATCH_IMAGE; String regex = Constant.Regex.MATCH_IMAGE;
Pattern pattern = Pattern.compile(regex); Pattern pattern = Pattern.compile(regex);
// 创建Matcher对象 // 创建Matcher对象
@@ -36,25 +35,26 @@ public class FriendMessageListener extends SimpleListenerHost {
url = matcher.group(1); 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)) { if (content.startsWith(Constant.Order.PREFIX_CUSTOM)) {
String[] split = content.split(ChatConstant.BLANK); chatCommand = content.split(Constant.Order.SPLIT_BLANK)[0];
chatCommand = split[0] + ChatConstant.BLANK; content = content.substring(chatCommand.length() + 1);
method = MethodsConstant.CUSTOM; } else {
content = content.substring((content.split(ChatConstant.BLANK)[0]+ChatConstant.BLANK).length()); chatCommand = Constant.Order.DEFAULT;
} else if (content.startsWith(ChatConstant.ONCE_MESSAGE_START)) {
content = content.substring(1);
method = MethodsConstant.ONCE;
} }
//发送请求并获取回应 //发送请求并获取回应
String response = switch (method) { String response;
case CUSTOM -> AIUtil.customChat(Long.valueOf(id), content, url, chatCommand); if (content.equals(Constant.Order.MSG_CLEAR)){
case ONCE -> AIUtil.chatOnce(content, url); //检测是否为清除指令
case NORMAL -> AIUtil.defaultChat(Long.valueOf(id), content, url); response = ChatUtil.removeClient(id, chatCommand);
default -> "ERROR!"; }else {
}; //发送请求并获取回应
response = ChatUtil.chat(id, content, chatCommand);
}
event.getFriend().sendMessage(response); event.getFriend().sendMessage(response);
} }
} }

View File

@@ -1,47 +1,36 @@
package plugin.listener; package plugin.listener;
import kotlin.coroutines.CoroutineContext; import lombok.extern.slf4j.Slf4j;
import net.mamoe.mirai.event.EventHandler; import net.mamoe.mirai.event.EventHandler;
import net.mamoe.mirai.event.SimpleListenerHost; import net.mamoe.mirai.event.SimpleListenerHost;
import net.mamoe.mirai.event.events.GroupMessageEvent; import net.mamoe.mirai.event.events.GroupMessageEvent;
import net.mamoe.mirai.message.data.At; import net.mamoe.mirai.message.data.At;
import org.jetbrains.annotations.NotNull; import plugin.chat.constant.Constant;
import plugin.constant.ChatConstant; import plugin.utils.ChatUtil;
import plugin.constant.Constant; import plugin.utils.OCRUtil;
import plugin.constant.MethodsConstant;
import plugin.pojo.Config;
import plugin.utils.AIUtil;
import plugin.utils.ConfigUtil;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import static plugin.utils.ConfigUtil.logger;
/** /**
* @author SLHAF * @author SLHAF
*/ */
@Slf4j
public class GroupMessageListener extends SimpleListenerHost { public class GroupMessageListener extends SimpleListenerHost {
@Override
public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) {
logger.warning(exception);
}
/** /**
* 负责提取链接、获取消息内容去除指令头提取指令、提取发送者id * 负责提取链接、获取消息内容去除指令头提取指令、提取发送者id
* @param event 接收群聊消息 * @param event 接收群聊消息
*/ */
@EventHandler @EventHandler
public void groupMessageHandler(GroupMessageEvent event) { public void groupMessageHandler(GroupMessageEvent event) {
Config config = ConfigUtil.getConfig();
//处理消息 //处理消息
String id = String.valueOf(event.getSender().getId()); String id = String.valueOf(event.getSender().getId());
String content = event.getMessage().contentToString(); String content = event.getMessage().contentToString();
String miraiCode = event.getMessage().serializeToMiraiCode(); String miraiCode = event.getMessage().serializeToMiraiCode();
String url = null; String url = null;
String chatCommand = null; String chatCommand;
if (miraiCode.matches(Constant.Regex.MATCH_MESSAGE)) { if (miraiCode.matches(Constant.Regex.MATCH_MESSAGE)) {
Pattern pattern = Pattern.compile(Constant.Regex.MATCH_IMAGE); Pattern pattern = Pattern.compile(Constant.Regex.MATCH_IMAGE);
@@ -54,36 +43,33 @@ public class GroupMessageListener extends SimpleListenerHost {
url = matcher.group(1); url = matcher.group(1);
} }
} }
if (OCRUtil.isSupported && url != null) {
MethodsConstant method = MethodsConstant.NONE; content = content + "```content\r\n" + OCRUtil.getContentOfImage(url) + "\r\n```";
}
//消息头处理 //消息头处理
if (content.startsWith(Constant.Order.PREFIX_ONECE)) { if (content.startsWith(Constant.Order.PREFIX_DEFAULT + event.getBot().getId())) {
//单次对话
content = content.substring(1);
method = MethodsConstant.ONCE;
} else if (content.startsWith(Constant.Order.PREFIX_DEFAULT + event.getBot().getId())) {
//默认对话 //默认对话
content = content.substring((Constant.Order.PREFIX_DEFAULT + event.getBot().getId()).length()); content = content.substring((Constant.Order.PREFIX_DEFAULT + event.getBot().getId()).length());
method = MethodsConstant.NORMAL; chatCommand = Constant.Order.DEFAULT;
} else if (config.getCustomCommands().containsKey(content.split(Constant.Order.SPLIT_BLANK)[0]+Constant.Order.SPLIT_BLANK)) { } else {
//预设对话 //预设对话
String[] split = content.split(Constant.Order.SPLIT_BLANK); String[] split = content.split(Constant.Order.SPLIT_BLANK);
chatCommand = split[0] + Constant.Order.SPLIT_BLANK; chatCommand = split[0];
method = MethodsConstant.CUSTOM; content = content.substring(chatCommand.length()+1);
content = content.substring(chatCommand.length());
} }
//消息内容处理 //消息内容处理
if (content.isBlank()) { if (content.isBlank()) {
content = "在吗"; content = "在吗";
} }
//发送请求并获取回应 String response;
String response = switch (method) { if (content.equals(Constant.Order.MSG_CLEAR)){
case CUSTOM -> AIUtil.customChat(Long.valueOf(id), content, url,chatCommand); //检测是否为清除指令
case NORMAL -> AIUtil.defaultChat(Long.valueOf(id), content, url); response = ChatUtil.removeClient(id, chatCommand);
case ONCE -> AIUtil.chatOnce(content, url); }else {
default -> Constant.Status.ERROR; //发送请求并获取回应
}; response = ChatUtil.chat(id, content, chatCommand);
}
event.getGroup().sendMessage(new At(Long.parseLong(id)).plus("\r\n").plus(response)); event.getGroup().sendMessage(new At(Long.parseLong(id)).plus("\r\n").plus(response));
} }
} }

View File

@@ -1,6 +1,6 @@
package plugin.listener; package plugin.listener;
import kotlin.coroutines.CoroutineContext; import lombok.extern.slf4j.Slf4j;
import net.mamoe.mirai.contact.Group; import net.mamoe.mirai.contact.Group;
import net.mamoe.mirai.event.EventHandler; import net.mamoe.mirai.event.EventHandler;
import net.mamoe.mirai.event.SimpleListenerHost; 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.GroupMessageEvent;
import net.mamoe.mirai.event.events.MessageEvent; import net.mamoe.mirai.event.events.MessageEvent;
import net.mamoe.mirai.message.data.At; import net.mamoe.mirai.message.data.At;
import org.jetbrains.annotations.NotNull; import plugin.chat.constant.Constant;
import plugin.constant.ChatConstant; import plugin.config.Config;
import plugin.constant.Constant; import plugin.config.CustomCommandTemplate;
import plugin.constant.ConfigConstant; import plugin.utils.ChatUtil;
import plugin.utils.AIUtil;
import plugin.utils.ConfigUtil;
import java.io.IOException; import java.io.IOException;
import static plugin.utils.ConfigUtil.logger;
/** /**
* @author SLHAF * @author SLHAF
*/ */
@Slf4j
public class OwnerMessageListener extends SimpleListenerHost { public class OwnerMessageListener extends SimpleListenerHost {
@Override
public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) {
super.handleException(context, exception);
logger.error(exception);
}
@EventHandler @EventHandler
public void messageClassifier(MessageEvent event) throws IOException { public void messageClassifier(MessageEvent event) throws IOException {
if (event.getSubject() instanceof Group) { if (event.getSubject() instanceof Group) {
@@ -45,23 +36,23 @@ public class OwnerMessageListener extends SimpleListenerHost {
if (!primaryContent.contains(Constant.Order.SPLIT_GUN)) { if (!primaryContent.contains(Constant.Order.SPLIT_GUN)) {
String response; String response;
response = switch (primaryContent) { response = switch (primaryContent) {
case "clearAll" -> AIUtil.clearAll(); case "clearAll" -> ChatUtil.removeAllClients();
case "shutUp" -> ConfigUtil.shutUp(event.getGroup().getId()); case "shutUp" -> Config.ConfigLoader.shutUp(event.getGroup().getId());
case "speak" -> ConfigUtil.speak(event.getGroup().getId()); case "speak" -> Config.ConfigLoader.speak(event.getGroup().getId());
default -> "无对应操作"; default -> "无对应操作";
}; };
event.getGroup().sendMessage(response); event.getGroup().sendMessage(response);
return; 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); String arguments = primaryContent.substring(primaryContent.indexOf(Constant.Order.SPLIT_GUN) + 1);
long id = event.getSender().getId(); long id = event.getSender().getId();
String response; String response;
try { try {
response = handleCommand(command, arguments); response = handleCommand(instruction, arguments);
} catch (Exception e) { } catch (Exception e) {
logger.error(e.toString()); log.error(e.toString());
response = "操作失败!\r\n" + e.getMessage(); response = "操作失败!\r\n" + e.getMessage();
} }
event.getGroup().sendMessage(new At(id).plus(response)); event.getGroup().sendMessage(new At(id).plus(response));
@@ -69,57 +60,84 @@ public class OwnerMessageListener extends SimpleListenerHost {
private void onFriendMessageEvent(FriendMessageEvent event) throws IOException { private void onFriendMessageEvent(FriendMessageEvent event) throws IOException {
String primaryContent = event.getMessage().contentToString().split(Constant.Order.SPLIT_BLANK)[1]; String primaryContent = event.getMessage().contentToString().split(Constant.Order.SPLIT_BLANK)[1];
String command; String instruction;
String arguments; String arguments;
try { 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); arguments = primaryContent.substring(primaryContent.indexOf(Constant.Order.SPLIT_CUSTOM) + 1);
} catch (ArrayIndexOutOfBoundsException e) { } catch (ArrayIndexOutOfBoundsException e) {
event.getFriend().sendMessage("操作失败,缺少参数"); event.getFriend().sendMessage("操作失败,缺少参数");
return; return;
} }
String response = handleCommand(command, arguments); String response = handleCommand(instruction, arguments);
event.getFriend().sendMessage(response); event.getFriend().sendMessage(response);
} }
/** /**
* 对命令及其参数进行处理 * 对命令及其参数进行处理
* *
* @param command 命令 * @param instruction 命令
* @param arguments 参数 * @param arguments 参数
* @return 处理结果 * @return 处理结果
*/ */
private String handleCommand(String command, String arguments) throws IOException { private String handleCommand(String instruction, String arguments) throws IOException {
return switch (command) { return switch (instruction) {
case "添加预设" -> { case "添加预设" -> {
if (arguments.matches(ConfigConstant.ADD_CUSTOM)) { if (arguments.matches(Constant.Regex.ADD_CUSTOM)) {
String instruction = arguments.split(ConfigConstant.CUSTOM_SPLIT)[0] + ChatConstant.BLANK; String[] argumentsArray = arguments.split(Constant.Order.SPLIT_CUSTOM);
String customModel = arguments.split(ConfigConstant.CUSTOM_SPLIT)[1]; String command = argumentsArray[0];
String customContent = arguments.split(ConfigConstant.CUSTOM_SPLIT)[2]; int modelTemplateIndex = Integer.parseInt(argumentsArray[1]);
yield ConfigUtil.addCustom(instruction, customModel, customContent); 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 { } else {
yield "格式不正确! 格式如下: \r\n" + ChatConstant.SET + "命令|预设指令|模型名称|预设\r\n例: \r\n" + ChatConstant.SPLIT + "/example|glm-4-flash|你是...\r\n注如果不需要预设可以将预设写为null"; yield "格式不正确!";
} }
} }
case "切换模型" -> { case "切换模型" -> {
if (arguments.matches(ConfigConstant.MODEL_CHANGE)) { if (arguments.matches(Constant.Order.MODEL_CHANGE)) {
String instruction = arguments.split(ConfigConstant.CUSTOM_SPLIT)[0] + ChatConstant.BLANK; //获取需更改的信息
String modelName = arguments.split(ConfigConstant.CUSTOM_SPLIT)[1]; String[] argumentsArray = arguments.split(Constant.Order.SPLIT_CUSTOM);
yield ConfigUtil.customModelChange(instruction, modelName); 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 { } else {
yield "格式不正确! 格式如下: \r\n" + ChatConstant.SET + "命令|预设指令|指令对应模型"; yield "格式不正确!";
} }
} }
case "更改预设" -> { case "更改预设" -> {
if (arguments.matches(ConfigConstant.MODEL_CHANGE)) { if (arguments.matches(Constant.Order.MODEL_CHANGE)) {
String instruction = arguments.split(ConfigConstant.CUSTOM_SPLIT)[0] + ChatConstant.BLANK; String[] argumentsArray = arguments.split(Constant.Order.SPLIT_CUSTOM);
String customContent = arguments.split(ConfigConstant.CUSTOM_SPLIT)[1]; String command = argumentsArray[0];
yield ConfigUtil.customContentChange(instruction, customContent); 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 { } else {
yield "格式不正确! 格式如下: \r\n" + ChatConstant.SET + "命令|预设指令|指令对应预设"; yield "格式不正确!";
} }
} }
case "删除预设" -> ConfigUtil.removeCustom(arguments); case "删除预设" -> Config.ConfigLoader.removeCustom(arguments);
default -> "该指令不存在!"; default -> "该指令不存在!";
}; };
} }

View File

@@ -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<Long> blacklist;
/**
* 自定义预设
*/
private LinkedHashMap<String,String> customCommands;
public Config() {
}
public Config(String apikey, String accessKeyId, String accessKeySecret, String owner, String defaultModel, String bot, String timeout, String timeCheck, LinkedHashMap<String, String> 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<Long> blacklist, LinkedHashMap<String, String> 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<String, String> getCustomCommands() {
return customCommands;
}
/**
* 设置
* @param customCommands
*/
public void setCustomCommands(LinkedHashMap<String, String> 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<Long> getBlacklist() {
return blacklist;
}
/**
* 设置
* @param blacklist
*/
public void setBlacklist(List<Long> blacklist) {
this.blacklist = blacklist;
}
}

View File

@@ -1,7 +1,12 @@
package plugin.pojo; package plugin.pojo;
import lombok.Getter;
import lombok.Setter;
import java.util.List; import java.util.List;
@Setter
@Getter
public class OCRDataInfo { public class OCRDataInfo {
/** /**
@@ -41,78 +46,6 @@ public class OCRDataInfo {
*/ */
private int width; 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<PrismWordsInfoBean> getPrism_wordsInfo() {
return prism_wordsInfo;
}
public void setPrism_wordsInfo(List<PrismWordsInfoBean> prism_wordsInfo) {
this.prism_wordsInfo = prism_wordsInfo;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public static class PrismWordsInfoBean { public static class PrismWordsInfoBean {
/** /**
* angle * angle

View File

@@ -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);
}
}

View File

@@ -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<ChatMessage> messages;
public UserCustomMessage() {
}
public UserCustomMessage(String command, List<ChatMessage> 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<ChatMessage> getMessages() {
return messages;
}
/**
* 设置
* @param messages
*/
public void setMessages(List<ChatMessage> messages) {
this.messages = messages;
}
@Override
public String toString() {
return "UserCustomMessage{command = " + command + ", messages = " + messages + "}";
}
}

View File

@@ -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<Long, List<ChatMessage>> userDefaultMessages = new HashMap<>();
private static final HashMap<Long, Long> userLatestTimeOfDefault = new HashMap<>();
private static String defaultModel;
private static final HashMap<Long, List<UserCustomMessage>> userCustomMessages = new HashMap<>();
private static final HashMap<Long, List<UserCustomLatestTime>> userLatestTimeOfCustom = new HashMap<>();
/*private static String modelCode;*/
/**
* 结构:
* /c : glm-4-flush|预设内容
*/
private static HashMap<String, String> 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<Integer> 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<Integer> indexToRemove = new ArrayList<>();
List<UserCustomMessage> 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<ChatMessage> 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<UserCustomMessage> userCustomMessageList = new ArrayList<>();
userCustomMessageList.add(new UserCustomMessage(chatCommand, chatMessages));
userCustomMessages.put(id, userCustomMessageList);
}else {
//存在消息记录,但需要判断是否存在该指令对应的消息记录
List<UserCustomMessage> 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<ChatMessage> 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<ChatMessage> 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<ChatMessage> 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 + ">";
}
}
/**
* 取得回复内容
* <br>chatMessages内容只有两个static变量只需根据传入的chatCommand是否为null进行判断
*
* @param id 聊天用户ID
* @param content 聊天用户发送的内容content已在Listener处进行处理
* @param url 获取到的图片url如果没有图片则为null
* @param model 本次对话所需的模型名称
* <br>当为userDefaultMessages时
* <br><code>
* <br> qq1 : [msg1,msg2,msg3]
* <br> qq2 : [msg1,msg2,msg3]
* <br></code>
* <br>当为userCustomMessages时
* <br><code>
* <br> qq1 : [{command1,[msg1.msg2,msg3]},{command2,[msg1,msg2,msg3]},{command3,[msg1,msg2,msg3]}]
* <br> qq2 : [{command1,[msg1.msg2,msg3]},{command2,[msg1,msg2,msg3]},{command3,[msg1,msg2,msg3]}]
* <br></code>
* @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<ChatMessage> chatMessages = null;
if (chatCommand == null) {
chatMessages = userDefaultMessages.get(id);
userLatestTimeOfDefault.put(id, System.currentTimeMillis());
} else {
List<UserCustomMessage> userCustomMessageList = userCustomMessages.get(id);
for (UserCustomMessage userCustomMessage : userCustomMessageList) {
//在调用时已确保存在指令对应的消息记录
if (userCustomMessage.getCommand().equals(chatCommand)) {
chatMessages = userCustomMessage.getMessages();
break;
}
}
//更新最新操作时间
boolean foundTime = false;
List<UserCustomLatestTime> 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 + "条会话";
}
}

View File

@@ -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<String, ChatClient> chatClients = new HashMap<>();
private static final HashMap<String,Long> 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 "所有消息记录已清空";
}
}

View File

@@ -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<Long> blacklist = new ArrayList<>();
blacklist.add(123456789L);
blacklist.add(987654321L);
config.setBlacklist(blacklist);
LinkedHashMap<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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 + "]成功";
}
}
}

View File

@@ -6,24 +6,23 @@ import com.aliyun.ocr_api20210707.models.RecognizeAdvancedRequest;
import com.aliyun.ocr_api20210707.models.RecognizeAdvancedResponse; import com.aliyun.ocr_api20210707.models.RecognizeAdvancedResponse;
import com.aliyun.tea.TeaException; import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions; import com.aliyun.teautil.models.RuntimeOptions;
import plugin.pojo.Config; import lombok.extern.slf4j.Slf4j;
import plugin.config.Config;
import plugin.pojo.OCRDataInfo; import plugin.pojo.OCRDataInfo;
import static plugin.utils.ConfigUtil.logger; @Slf4j
public class OCRUtil { public class OCRUtil {
private static Client client; private static Client client;
public static boolean isSupported; public static boolean isSupported;
static { static {
//读取密钥 //读取密钥
Config pluginConfig = ConfigUtil.getConfig(); Config pluginConfig = Config.ConfigLoader.getConfig();
String accessKeyId = pluginConfig.getAccessKeyId(); String accessKeyId = pluginConfig.getOcrConfig().getAccessKeyId();
String accessKeySecret = pluginConfig.getAccessKeySecret(); String accessKeySecret = pluginConfig.getOcrConfig().getAccessKeySecret();
if (accessKeySecret == null || accessKeyId == null) { if (accessKeySecret == null || accessKeyId == null) {
isSupported = false; isSupported = false;
logger.warning("未检测到阿里云OCR配置信息图片文字识别将不可用。"); log.warn("未检测到阿里云OCR配置信息图片文字识别将不可用。");
} else { } else {
isSupported = true; isSupported = true;
com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config() com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
@@ -33,10 +32,10 @@ public class OCRUtil {
try { try {
client = new Client(config); client = new Client(config);
} catch (Exception e) { } catch (Exception e) {
logger.error("创建client出错"); log.error("创建client出错");
logger.error(e.getMessage()); log.error(e.getMessage());
} }
logger.info("阿里云OCR已配置。"); log.info("阿里云OCR已配置。");
} }
} }
@@ -65,18 +64,18 @@ public class OCRUtil {
} catch (TeaException error) { } catch (TeaException error) {
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message // 错误 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); com.aliyun.teautil.Common.assertAsString(error.message);
return "ERROR"; return "ERROR";
} catch (Exception _error) { } catch (Exception _error) {
TeaException error = new TeaException(_error.getMessage(), _error); TeaException error = new TeaException(_error.getMessage(), _error);
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。 // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
// 错误 message // 错误 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); com.aliyun.teautil.Common.assertAsString(error.message);
return "ERROR"; return "ERROR";
} }

View File

@@ -14,19 +14,10 @@ import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import org.junit.Test; import org.junit.Test;
import plugin.App; 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.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner; import java.util.Scanner;
import static kotlin.io.ConsoleKt.readln;
public class MyTest { public class MyTest {
@Test @Test
@@ -128,57 +119,6 @@ public class MyTest {
client.close(); 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 @Test
public void terminalTest() throws InterruptedException { public void terminalTest() throws InterruptedException {