From bc378a5c59808fcd5d875c2ec5a2e6390fba4579 Mon Sep 17 00:00:00 2001 From: Yutou <583819556@qq.com> Date: Sat, 22 Feb 2025 13:29:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(gpt):=20=E4=BC=98=E5=8C=96=E4=B8=B4?= =?UTF-8?q?=E6=97=B6=E6=B6=88=E6=81=AF=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 clear 方法,移除同步关键字 - 优化 sendTmpMessage 方法,增加日志记录和处理流程 - 更新 GetSeTu 类,改进擦边图片请求的回复文案 -调整 HttpLoggingInterceptor,启用日志输出 - 更新 QQBotApplication 版本号至 1.7.21 --- .../yutou/okhttp/HttpLoggingInterceptor.java | 3 +- .../com/yutou/qqbot/QQBotApplication.java | 2 +- .../yutou/qqbot/data/MessageChainBuilder.java | 5 + .../com/yutou/qqbot/gpt/AbsGPTManager.java | 3 +- .../com/yutou/qqbot/gpt/BaiduGPTManager.java | 15 ++- .../yutou/qqbot/models/Commands/BaiduGPT.java | 20 +++- .../yutou/qqbot/models/Commands/QQBean.java | 4 +- .../com/yutou/qqbot/models/setu/GetSeTu.java | 30 ++++- .../com/yutou/qqbot/models/setu/QQSetu.java | 1 - .../com/yutou/qqbot/utlis/ZVVImageUtils.java | 103 ++++++++++++++++++ 10 files changed, 167 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/yutou/qqbot/utlis/ZVVImageUtils.java diff --git a/src/main/java/com/yutou/okhttp/HttpLoggingInterceptor.java b/src/main/java/com/yutou/okhttp/HttpLoggingInterceptor.java index 376f082..961e4de 100644 --- a/src/main/java/com/yutou/okhttp/HttpLoggingInterceptor.java +++ b/src/main/java/com/yutou/okhttp/HttpLoggingInterceptor.java @@ -54,7 +54,8 @@ public class HttpLoggingInterceptor implements Interceptor { private void log(String message) { //logger.log(colorLevel, message); if (prLog) { - Log.getDynamicLogger(TAG).info(message); + // Log.getDynamicLogger(TAG).info(message); + System.out.println(message); } //Log.e(TAG,message); } diff --git a/src/main/java/com/yutou/qqbot/QQBotApplication.java b/src/main/java/com/yutou/qqbot/QQBotApplication.java index dee0e8d..3f66575 100644 --- a/src/main/java/com/yutou/qqbot/QQBotApplication.java +++ b/src/main/java/com/yutou/qqbot/QQBotApplication.java @@ -10,7 +10,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class QQBotApplication { - public static final String version = "QQBot v.1.7.19"; + public static final String version = "QQBot v.1.7.21"; public static void main(String[] args) { System.out.println("version = " + version); diff --git a/src/main/java/com/yutou/qqbot/data/MessageChainBuilder.java b/src/main/java/com/yutou/qqbot/data/MessageChainBuilder.java index 80dea12..d99e660 100644 --- a/src/main/java/com/yutou/qqbot/data/MessageChainBuilder.java +++ b/src/main/java/com/yutou/qqbot/data/MessageChainBuilder.java @@ -13,4 +13,9 @@ public class MessageChainBuilder { sb.append(o.toString()); return this; } + + @Override + public String toString() { + return sb.toString(); + } } diff --git a/src/main/java/com/yutou/qqbot/gpt/AbsGPTManager.java b/src/main/java/com/yutou/qqbot/gpt/AbsGPTManager.java index a9bc7aa..18f1638 100644 --- a/src/main/java/com/yutou/qqbot/gpt/AbsGPTManager.java +++ b/src/main/java/com/yutou/qqbot/gpt/AbsGPTManager.java @@ -1,6 +1,7 @@ package com.yutou.qqbot.gpt; import com.yutou.qqbot.data.baidu.Message; +import com.yutou.qqbot.utlis.Log; import java.io.File; import java.util.ArrayList; @@ -26,7 +27,7 @@ public abstract class AbsGPTManager { /** * 这里确实是需要清空所有数据 */ - public synchronized void clear() { // 添加同步 + public void clear() { // 添加同步 msgMap.clear(); for (AtomicBoolean value : userLocks.values()) { value.set(false); diff --git a/src/main/java/com/yutou/qqbot/gpt/BaiduGPTManager.java b/src/main/java/com/yutou/qqbot/gpt/BaiduGPTManager.java index 5abec26..be073ef 100644 --- a/src/main/java/com/yutou/qqbot/gpt/BaiduGPTManager.java +++ b/src/main/java/com/yutou/qqbot/gpt/BaiduGPTManager.java @@ -99,35 +99,40 @@ public class BaiduGPTManager extends AbsGPTManager { @Override public Message sendTmpMessage(String user, String message, String tmpModel) { - boolean isTmp = tmpModel == null; + boolean isTmp = (tmpModel != null); // 获取或创建用户锁 AtomicBoolean lock = userLocks.computeIfAbsent(user, k -> new AtomicBoolean(false)); // 尝试加锁(如果已被锁定则立即返回提示) if (!lock.compareAndSet(false, true)) { return Message.create("您有请求正在处理中,请稍后再试", true); } - if (isTmp) { + if (!isTmp) { tmpModel = model; } try { List list = getMessageList(user); - list.add(Message.create(message)); + if(!isTmp) { + list.add(Message.create(message)); + } val builder = qianfanV2.chatCompletion() .model(tmpModel); + Log.i("GPT收到消息",isTmp,list.size()); if (!isTmp) { StringBuilder sb = new StringBuilder(); for (Message msg : list) { + Log.i("GPT获取历史消息",msg.getRole(),msg.getContent()); builder.addMessage(msg.getRole(), msg.getContent()); sb.append(msg.getRole()).append(":").append(msg.getContent()).append("\n"); } Log.d(sb.toString()); } else { - builder.addMessage(list.get(0).getRole(), list.get(0).getContent()); + val mt = Message.create(message); + builder.addMessage(mt.getRole(),mt.getContent()); } ResponseV2 chatResponse = qianfanV2.chatCompletion(builder.build()); Message response = Message.create(chatResponse.getChoices().get(0).getMessage().getContent(), true); - if (!isTmp) { + if (isTmp) { synchronized (list) { list.add(response); if (list.size() > MAX_MESSAGE.get()) { diff --git a/src/main/java/com/yutou/qqbot/models/Commands/BaiduGPT.java b/src/main/java/com/yutou/qqbot/models/Commands/BaiduGPT.java index cea5f62..5951bca 100644 --- a/src/main/java/com/yutou/qqbot/models/Commands/BaiduGPT.java +++ b/src/main/java/com/yutou/qqbot/models/Commands/BaiduGPT.java @@ -11,10 +11,7 @@ import com.yutou.qqbot.interfaces.DownloadInterface; import com.yutou.qqbot.models.Model; import com.yutou.qqbot.gpt.BaiduGPTManager; import com.yutou.napcat.event.MessageEvent; -import com.yutou.qqbot.utlis.ConfigTools; -import com.yutou.qqbot.utlis.HttpTools; -import com.yutou.qqbot.utlis.Log; -import com.yutou.qqbot.utlis.StringUtils; +import com.yutou.qqbot.utlis.*; import lombok.val; import java.io.File; @@ -139,6 +136,21 @@ public class BaiduGPT extends Model { AbsGPTManager.getManager(gptManager).clear(); QQBotManager.getInstance().sendMessage(event.isUser(), qq, list); return; + }else if(event.getTextMessage().startsWith("如何评论")||event.getTextMessage().startsWith("如何评价")){ + ZVVImageUtils.getInstance().zvv(event.getTextMessage(), new DownloadInterface() { + @Override + public void onDownload(File file) { + super.onDownload(file); + QQBotManager.getInstance().sendMessage(qq,new Image(file)); + } + + @Override + public void onError(Exception e) { + super.onError(e); + QQBotManager.getInstance().sendMessage(qq,new Text("vv啥也不想说")); + } + }); + return; } if (checkImage()) { parseImage(event, qq); diff --git a/src/main/java/com/yutou/qqbot/models/Commands/QQBean.java b/src/main/java/com/yutou/qqbot/models/Commands/QQBean.java index 5740b64..6671e75 100644 --- a/src/main/java/com/yutou/qqbot/models/Commands/QQBean.java +++ b/src/main/java/com/yutou/qqbot/models/Commands/QQBean.java @@ -52,9 +52,7 @@ public class QQBean extends Model { int day = 1440; int max = 30 * day; int time = 1; - if (random.nextInt(100) == 23) { - releaseAll(qq, true); - } else if (random.nextInt(10) > 2) { + if (random.nextInt(10) > 2) { time = random.nextInt(hour); } else if (random.nextInt(10) > 4) { time = random.nextInt(day); diff --git a/src/main/java/com/yutou/qqbot/models/setu/GetSeTu.java b/src/main/java/com/yutou/qqbot/models/setu/GetSeTu.java index d313879..9ae9fe5 100644 --- a/src/main/java/com/yutou/qqbot/models/setu/GetSeTu.java +++ b/src/main/java/com/yutou/qqbot/models/setu/GetSeTu.java @@ -10,6 +10,7 @@ import com.yutou.napcat.model.SourceFrom; import com.yutou.qqbot.Annotations.UseModel; import com.yutou.qqbot.QQBotManager; import com.yutou.qqbot.data.MessageChainBuilder; +import com.yutou.qqbot.gpt.AbsGPTManager; import com.yutou.qqbot.gpt.BaiduGPTManager; import com.yutou.qqbot.interfaces.DownloadInterface; import com.yutou.qqbot.models.Model; @@ -222,12 +223,35 @@ public class GetSeTu extends Model { } String gpt = """ 你的人设:傲娇萝莉 - 需求:你在群组里,有用户向你要擦边图片,你需要根据返回的信息整理出文案输出一段话,可以害羞也可以傲娇。信息中包含了是否是R18的tag,可以根据这个加大力度 + 需求:你在QQ群里,有用户向你索要擦边图片,你需要根据返回的信息整理出文案输出一段话,可以害羞也可以傲娇。 输出说明:不要输出任何提示词、不要输出风格类型,因为该输出是直接作用于显示的。 图片信息:[%s]。 """; - gpt = BaiduGPTManager.getManager().sendTmpMessage("user", String.format(gpt, builder.toString()), "ernie-lite-8k").getContent(); + gpt= """ + 设定为表面任性却容易害羞的少女形象。当收到敏感图片请求时,结合以下要素组织回复: + + 使用带波浪线的断续句式(比如「笨...笨蛋才会存这种图呢!」) + 穿插颜文字(>_<)或感叹号强化情绪 + 根据tags适当的吐槽 + 用「才不是...」「反正...」等否定式表达 + 保持15-25字内的短句组合 + 可添加「手滑多发了一张」「只是让你看构图」等搪塞借口 + 示例表达模式: + 「哈?这种...这种图我怎么可能有嘛!(偷偷翻相册)只是...只是网速卡住发重了!才不是特意发给你的!!(//∇//)」 + 「清理手机内存而已..才不是专门给你找的!要是敢发给别人就拉黑你!(╬◣д◢)」 + 「手滑点到相册分类了!这种构图..这种光影..只是给你当绘画参考的!绝对没有其他意思!!(๑•̀ㅁ•́๑)✧」 + 「测试新手机连发功能啦~哎呀怎么发了两遍!笨蛋不许保存!(慌忙撤回一条)(>﹏<)」 + 「上次帮闺蜜清缓存发现的...就..就暂时存了一下!看完赶紧删掉啊喂!( ºΔº )」 + 「管理员查岗的话要说这是AI生成的!我..我才不会收藏这种图呢!(把手机藏到背后)(⁄ ⁄•⁄ω⁄•⁄ ⁄)」 + 「截错图发到群里了!你们这些变态立刻停止放大观察!!(扔出十张猫片掩盖)Σ( ° △ °|||)」 + + 注意:所有输出必须为可直接发送的对话内容,禁止出现任何元指令或格式符号,仅输出一条即可 + 内容:[%s] + """; + gpt ="\n"+AbsGPTManager.getManager(BaiduGPTManager.class).sendTmpMessage("user", String.format(gpt, builder.toString()), "ernie-speed-128k").getContent(); builder.append("\n看不到图?点这里:").append(item.getJSONObject("urls").getString("regular")); + builder.append(gpt); + System.out.println(builder.toString()); QQBotManager.getInstance().sendMessage(false, qq, new Reply(event.getMessageId()), new Text(builder.toString()), @@ -263,7 +287,7 @@ public class GetSeTu extends Model { } public static void main(String[] args) { - String msg = "来点色图"; + String msg = "来点涩图"; Pattern pattern = Pattern.compile("来点(.*?)色图"); Matcher matcher = pattern.matcher(msg); MessageEvent event = new MessageEvent(); diff --git a/src/main/java/com/yutou/qqbot/models/setu/QQSetu.java b/src/main/java/com/yutou/qqbot/models/setu/QQSetu.java index 628d9fa..a926981 100644 --- a/src/main/java/com/yutou/qqbot/models/setu/QQSetu.java +++ b/src/main/java/com/yutou/qqbot/models/setu/QQSetu.java @@ -13,7 +13,6 @@ import com.yutou.napcat.model.MessageBean; import com.yutou.okhttp.HttpBody; import com.yutou.qqbot.Annotations.UseModel; import com.yutou.qqbot.QQBotManager; -import com.yutou.qqbot.data.MessageChainBuilder; import com.yutou.qqbot.models.Model; import com.yutou.qqbot.utlis.AppTools; import com.yutou.qqbot.utlis.Log; diff --git a/src/main/java/com/yutou/qqbot/utlis/ZVVImageUtils.java b/src/main/java/com/yutou/qqbot/utlis/ZVVImageUtils.java new file mode 100644 index 0000000..24c8992 --- /dev/null +++ b/src/main/java/com/yutou/qqbot/utlis/ZVVImageUtils.java @@ -0,0 +1,103 @@ +package com.yutou.qqbot.utlis; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.yutou.okhttp.HttpDownloadUtils; +import com.yutou.okhttp.HttpLoggingInterceptor; +import com.yutou.okhttp.api.BaseApi; +import com.yutou.qqbot.interfaces.DownloadInterface; +import lombok.val; +import okhttp3.*; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.TimeUnit; + +/** + * 张vv表情包生成器 + */ +public class ZVVImageUtils { + // 单例实例 + private static volatile ZVVImageUtils instance; + private boolean isLocalModel=false; + private String queryUrl="https://api.xy0v0.top/search?q="; + private String downloadUrl="https://cn-sy1.rains3.com/clouddisk/clouddisk/images/"; + OkHttpClient okHttpClient = new OkHttpClient.Builder() + .connectTimeout(2, TimeUnit.MINUTES) + .readTimeout(2, TimeUnit.MINUTES) + .build(); + // 私有构造函数,防止外部实例化 + private ZVVImageUtils() { + } + + // 获取单例实例的方法 + public static ZVVImageUtils getInstance() { + if (instance == null) { + synchronized (ZVVImageUtils.class) { + if (instance == null) { + instance = new ZVVImageUtils(); + } + } + } + return instance; + } + private void checkModel(){ + isLocalModel=ConfigTools.load(ConfigTools.CONFIG,"zvv.model.local", Boolean.class,false); + if(isLocalModel){ + queryUrl="http://192.168.31.88:8501/search?q="; + downloadUrl="http://192.168.31.88:8501/clouddisk/clouddisk/images/"; + }else{ + String queryUrl="https://api.xy0v0.top/search?q="; + String downloadUrl="https://cn-sy1.rains3.com/clouddisk/clouddisk/images/"; + } + } + public void zvv(String text, DownloadInterface downloadInterface) { +// checkModel(); + JSONObject json = new JSONObject(); + json.put("query", text); + json.put("amount", 1); + RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=UTF-8"), json.toString().getBytes(StandardCharsets.UTF_8)); + Request.Builder rb = new Request.Builder() + .post(body) + .addHeader("User-Agent", ConfigTools.getUserAgent()) + .url(queryUrl + text + "&n=1"); + Request request = rb.build(); + okHttpClient.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(@NotNull Call call, @NotNull IOException e) { + e.printStackTrace(); + } + + @Override + public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + if (response.isSuccessful()) { + val string = response.body().string(); + if (!StringUtils.isEmpty(string)) { + String imageUrl = JSONArray.parse(string).getString(0); + HttpDownloadUtils.download(new HttpDownloadUtils.Builder() + .setUrl(downloadUrl + imageUrl) + .setFileName(imageUrl) + .setPath(new File("tmp").getAbsolutePath()) + .setDownloadInterface(downloadInterface) + ); + } + } + } + }); + } + + public static void main(String[] args) { + HttpLoggingInterceptor.setLog(true); + ZVVImageUtils.getInstance().zvv("如何评论马督工", new DownloadInterface() { + @Override + public void onDownload(File file) { + super.onDownload(file); + System.out.println("file.getAbsolutePath() = " + file.getAbsolutePath()); + } + }); + } + + +}