feat(gpt): 新增临时消息发送功能并优化相关命令

- 在 AbsGPTManager 中添加 sendTmpMessage 方法,用于发送临时消息
- 更新 BaiduGPTManager 实现 sendTmpMessage 方法
- 修改 GetSeTu 和 QQBean模型,集成临时消息发送功能
- 更新 BaiduGPT 示例代码,演示临时消息发送用法
- 将 QQBot 版本号更新到 v1.7.17
This commit is contained in:
Yutou 2025-02-19 17:10:42 +08:00
parent a7676fa6db
commit 925a7af045
7 changed files with 115 additions and 46 deletions

View File

@ -10,7 +10,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication @SpringBootApplication
public class QQBotApplication { public class QQBotApplication {
public static final String version = "QQBot v.1.7.15"; public static final String version = "QQBot v.1.7.17";
public static void main(String[] args) { public static void main(String[] args) {
System.out.println("version = " + version); System.out.println("version = " + version);

View File

@ -43,6 +43,7 @@ public abstract class AbsGPTManager {
* @return 包含消息发送结果的Message对象 * @return 包含消息发送结果的Message对象
*/ */
public abstract Message sendMessage(String user, String message); public abstract Message sendMessage(String user, String message);
public abstract Message sendTmpMessage(String user, String message, String tmpModel);
/** /**
* 将文本转换为图像 * 将文本转换为图像
@ -111,6 +112,11 @@ public abstract class AbsGPTManager {
return null; return null;
} }
@Override
public Message sendTmpMessage(String user, String message, String tmpModel) {
return null;
}
@Override @Override
public File textToImage(String user, String text) { public File textToImage(String user, String text) {
return null; return null;

View File

@ -68,7 +68,6 @@ public class BaiduGPTManager extends AbsGPTManager {
} }
// 这个是官方的示例代码表示连续对话 // 这个是官方的示例代码表示连续对话
private static void exampleChat() { private static void exampleChat() {
Qianfan qianfan = new Qianfan(); Qianfan qianfan = new Qianfan();
@ -83,38 +82,58 @@ public class BaiduGPTManager extends AbsGPTManager {
.execute(); .execute();
System.out.println("输出内容:" + response.getResult()); System.out.println("输出内容:" + response.getResult());
} }
/** /**
* 发送消息方法 * 发送消息方法
* 该方法用于处理用户发送的消息并返回相应的回复消息 * 该方法用于处理用户发送的消息并返回相应的回复消息
* 它通过用户锁来限制每个用户同时只能有一个请求正在处理中 * 它通过用户锁来限制每个用户同时只能有一个请求正在处理中
* *
* @param user 用户标识符用于区分不同的用户 * @param user 用户标识符用于区分不同的用户
* @param message 用户发送的消息内容 * @param message 用户发送的消息内容
* @return 返回处理后的消息对象包含回复内容和是否为回复消息的标记 * @return 返回处理后的消息对象包含回复内容和是否为回复消息的标记
*/ */
@Override @Override
public Message sendMessage(String user, String message) { public Message sendMessage(String user, String message) {
return sendTmpMessage(user, message, null);
}
@Override
public Message sendTmpMessage(String user, String message, String tmpModel) {
boolean isTmp = tmpModel == null;
// 获取或创建用户锁 // 获取或创建用户锁
AtomicBoolean lock = userLocks.computeIfAbsent(user, k -> new AtomicBoolean(false)); AtomicBoolean lock = userLocks.computeIfAbsent(user, k -> new AtomicBoolean(false));
// 尝试加锁如果已被锁定则立即返回提示 // 尝试加锁如果已被锁定则立即返回提示
if (!lock.compareAndSet(false, true)) { if (!lock.compareAndSet(false, true)) {
return Message.create("您有请求正在处理中,请稍后再试", true); return Message.create("您有请求正在处理中,请稍后再试", true);
} }
if (isTmp) {
tmpModel = model;
}
try { try {
List<Message> list = getMessageList(user); List<Message> list = getMessageList(user);
list.add(Message.create(message)); list.add(Message.create(message));
val builder = qianfanV2.chatCompletion() val builder = qianfanV2.chatCompletion()
.model(model); .model(tmpModel);
for (Message msg : list) {
builder.addMessage(msg.getRole(), msg.getContent()); if (!isTmp) {
StringBuilder sb = new StringBuilder();
for (Message msg : list) {
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());
} }
ResponseV2 chatResponse = qianfanV2.chatCompletion(builder.build()); ResponseV2 chatResponse = qianfanV2.chatCompletion(builder.build());
Message response = Message.create(chatResponse.getChoices().get(0).getMessage().getContent(), true); Message response = Message.create(chatResponse.getChoices().get(0).getMessage().getContent(), true);
synchronized (list) { if (!isTmp) {
list.add(response); synchronized (list) {
if (list.size() > MAX_MESSAGE.get()) { list.add(response);
int overflow = list.size() - MAX_MESSAGE.get(); if (list.size() > MAX_MESSAGE.get()) {
list.subList(0, overflow).clear(); int overflow = list.size() - MAX_MESSAGE.get();
list.subList(0, overflow).clear();
}
} }
} }
// msgMap.put(user, list); // msgMap.put(user, list);
@ -138,29 +157,29 @@ public class BaiduGPTManager extends AbsGPTManager {
* @return 返回生成的图像文件对象如果转换过程中发生错误则返回null * @return 返回生成的图像文件对象如果转换过程中发生错误则返回null
*/ */
@Override @Override
public File textToImage(String user, String text) { public File textToImage(String user, String text) {
try { try {
// 使用QianFan的text2Image方法将文本转换为图像数据 // 使用QianFan的text2Image方法将文本转换为图像数据
Text2ImageResponse response = qianfan.text2Image() Text2ImageResponse response = qianfan.text2Image()
.prompt(text) .prompt(text)
.execute(); .execute();
// 获取转换后的图像数据以Base64编码的图像字符串形式 // 获取转换后的图像数据以Base64编码的图像字符串形式
val b64Image = response.getData().get(0).getB64Image(); val b64Image = response.getData().get(0).getB64Image();
// 将Base64编码的图像数据转换为图像文件 // 将Base64编码的图像数据转换为图像文件
// 创建一个临时目录下的图像文件文件名包含用户标识符和当前时间戳以确保唯一性 // 创建一个临时目录下的图像文件文件名包含用户标识符和当前时间戳以确保唯一性
val imageFile = new File("tmp" + File.separator + user + "_" + System.currentTimeMillis() + ".png"); val imageFile = new File("tmp" + File.separator + user + "_" + System.currentTimeMillis() + ".png");
try (val inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(b64Image))) { try (val inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(b64Image))) {
// 将解码后的图像数据复制到图像文件中替换现有文件 // 将解码后的图像数据复制到图像文件中替换现有文件
Files.copy(inputStream, imageFile.toPath(), StandardCopyOption.REPLACE_EXISTING); Files.copy(inputStream, imageFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
return imageFile; return imageFile;
}
} catch (Exception e) {
// 如果在图像文件生成过程中发生错误记录错误信息
Log.e(e);
} }
} catch (Exception e) { // 如果发生错误返回null
// 如果在图像文件生成过程中发生错误记录错误信息 return null;
Log.e(e);
} }
// 如果发生错误返回null
return null;
}
/** /**

View File

@ -39,7 +39,10 @@ public class SiliconGPTManager extends AbsGPTManager {
} }
return instance; return instance;
} }
@Override
public Message sendTmpMessage(String user, String message, String tmpModel) {
return null;
}
@Override @Override
public synchronized Message sendMessage(String user, String message) { public synchronized Message sendMessage(String user, String message) {
// 获取或创建用户锁 // 获取或创建用户锁
@ -89,6 +92,8 @@ public class SiliconGPTManager extends AbsGPTManager {
} }
@Override @Override
public AbsGPTManager setModel(String model) { public AbsGPTManager setModel(String model) {
ConfigTools.save(ConfigTools.CONFIG, ConfigTools.GPT_SILICON, model); ConfigTools.save(ConfigTools.CONFIG, ConfigTools.GPT_SILICON, model);

View File

@ -149,11 +149,11 @@ public class BaiduGPT extends Model {
String.valueOf(qq), String.valueOf(qq),
event.getTextMessage().replace("@" + QQDatabase.getMe().getUserId(), "").trim()); event.getTextMessage().replace("@" + QQDatabase.getMe().getUserId(), "").trim());
String sb = "调用版本:" + String sb = "调用版本:" +
gptManager.getSimpleName()+ gptManager.getSimpleName() +
"\n" + "\n" +
"使用模型:"+ "使用模型:" +
AbsGPTManager.getManager(gptManager).getGPTVersion() + AbsGPTManager.getManager(gptManager).getGPTVersion() +
"\n"+ "\n" +
message.getContent(); message.getContent();
QQBotManager.getInstance().sendMessage(event.isUser(), qq, new Text(sb)); QQBotManager.getInstance().sendMessage(event.isUser(), qq, new Text(sb));
AbsGPTManager.getManager(gptManager).sendMessageAndScheduleClear(); AbsGPTManager.getManager(gptManager).sendMessageAndScheduleClear();
@ -194,6 +194,19 @@ public class BaiduGPT extends Model {
/* BaiduGPTManager.getManager().clear(); /* BaiduGPTManager.getManager().clear();
BaiduGPTManager.getManager().setModelFor35(); BaiduGPTManager.getManager().setModelFor35();
new BaiduGPT().onMessage(123456789L, messageEvent, false);*/ new BaiduGPT().onMessage(123456789L, messageEvent, false);*/
System.out.println(BaiduGPTManager.getManager().sendMessage("user", "宫廷玉液酒减去大锤等于多少")); String gpt = """
你的人设傲娇萝莉
需求你需要在符合人设的基础上用指定风格去嘲讽一个用户该用户是被你禁言的被禁言的用户喜欢被你禁言所以要一遍嘲讽一遍鼓励用户
提供被禁言时间()减免时间(),其中减免时间是禁言时间-减免时间=实际时间如被禁言360分减免60分就是被禁言了300分
风格基础:时间比较少使用贴吧风格,时间在一天内为微博风格,时间大于等于一天为小红书风格
条件1:如果有减免时间就在基础上狠狠的嘲讽
条件2:时间为0的不输出相关描述
特殊情况可能出现禁言时间为0的状态这时候以鼓励惊讶的口吻为主
输出说明仅使用一种风格不要输出任何提示词不要输出风格类型因为该输出是直接作用于显示的时间以口语化小时分钟描述
信息被禁言时间[%s],减免时间[%s]
""";
gpt = String.format(gpt, 360, 60);
System.err.println(gpt);
System.out.println(BaiduGPTManager.getManager().sendTmpMessage("user", gpt, "ernie-lite-8k"));
} }
} }

View File

@ -2,6 +2,7 @@ package com.yutou.qqbot.models.Commands;
import com.yutou.napcat.event.MessageEvent; import com.yutou.napcat.event.MessageEvent;
import com.yutou.napcat.handle.At; import com.yutou.napcat.handle.At;
import com.yutou.napcat.handle.BaseHandle;
import com.yutou.napcat.handle.Text; import com.yutou.napcat.handle.Text;
import com.yutou.napcat.http.NapCatApi; import com.yutou.napcat.http.NapCatApi;
import com.yutou.napcat.model.GroupUserBean; import com.yutou.napcat.model.GroupUserBean;
@ -9,6 +10,7 @@ import com.yutou.okhttp.BaseBean;
import com.yutou.okhttp.HttpCallback; import com.yutou.okhttp.HttpCallback;
import com.yutou.qqbot.Annotations.UseModel; import com.yutou.qqbot.Annotations.UseModel;
import com.yutou.qqbot.QQBotManager; import com.yutou.qqbot.QQBotManager;
import com.yutou.qqbot.gpt.BaiduGPTManager;
import com.yutou.qqbot.interfaces.ObjectInterface; import com.yutou.qqbot.interfaces.ObjectInterface;
import com.yutou.qqbot.models.Model; import com.yutou.qqbot.models.Model;
import com.yutou.qqbot.utlis.RedisTools; import com.yutou.qqbot.utlis.RedisTools;
@ -62,17 +64,31 @@ public class QQBean extends Model {
@Override @Override
public void out(String data) { public void out(String data) {
super.out(data); super.out(data);
int tmp = 0;
if (data != null) { if (data != null) {
QQBotManager.getInstance().sendMessage(event.isUser(), qq, List<BaseHandle<?>> list = new ArrayList<>();
new Text("恭喜"), list.add(new Text("恭喜"));
new At(user), list.add(new At(user));
new Text("获得了" + sendTime + "分钟的禁言," + sendAchievement(qq, user, sendTime)) list.add(new Text("获得了" + sendTime + "分钟的禁言," + sendAchievement(qq, user, sendTime)));
);
if (sendTime > day && random.nextInt(10) >= 3) { if (sendTime > day && random.nextInt(10) >= 3) {
int tmp = random.nextInt(sendTime / 2, sendTime); tmp = random.nextInt(sendTime / 2, sendTime);
QQBotManager.getInstance().groupBan(qq, user, (sendTime - tmp) * 60, null); QQBotManager.getInstance().groupBan(qq, user, (sendTime - tmp) * 60, null);
QQBotManager.getInstance().sendMessage(qq, "触发减伤:-" + tmp); list.add(new Text("触发减伤:-" + tmp));
} }
String gpt = """
你的人设傲娇萝莉
需求你需要在符合人设的基础上用指定风格去嘲讽一个用户该用户是被你禁言的被禁言的用户喜欢被你禁言所以要一遍嘲讽一遍鼓励用户
提供被禁言时间()减免时间(),其中减免时间是禁言时间-减免时间=实际时间如被禁言360分减免60分就是被禁言了300分
风格基础:时间比较少使用贴吧风格,时间在一天内为微博风格,时间大于等于一天为小红书风格
条件1:如果有减免时间就在基础上狠狠的嘲讽
条件2:时间为0的不输出相关描述
特殊情况可能出现禁言时间为0的状态这时候以鼓励惊讶的口吻为主
输出说明仅使用一种风格不要输出任何提示词不要输出风格类型因为该输出是直接作用于显示的时间以口语化小时分钟描述
信息被禁言时间[%s],减免时间[%s]
""";
gpt ="\n"+BaiduGPTManager.getManager().sendTmpMessage("user", String.format(gpt, sendTime, tmp), "ernie-lite-8k").getContent();
list.add(new Text(gpt));
QQBotManager.getInstance().sendMessage(event.isUser(), qq, list);
} }
} }
}); });
@ -116,7 +132,7 @@ public class QQBean extends Model {
if (!isRelease) { if (!isRelease) {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (GroupUserBean bean : shutList) { for (GroupUserBean bean : shutList) {
sb.append(bean.getNickname()).append(":").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.CHINA).format(new Date(bean.getShutUpTimestamp()))).append("\n"); sb.append(bean.getNickname()).append(":").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(new Date(bean.getShutUpTimestamp()))).append("\n");
} }
QQBotManager.getInstance().sendMessage(qq, "当前塞了:" + shutList.size() + "" + "\n" + sb); QQBotManager.getInstance().sendMessage(qq, "当前塞了:" + shutList.size() + "" + "\n" + sb);
return; return;

View File

@ -10,6 +10,7 @@ import com.yutou.napcat.model.SourceFrom;
import com.yutou.qqbot.Annotations.UseModel; import com.yutou.qqbot.Annotations.UseModel;
import com.yutou.qqbot.QQBotManager; import com.yutou.qqbot.QQBotManager;
import com.yutou.qqbot.data.MessageChainBuilder; import com.yutou.qqbot.data.MessageChainBuilder;
import com.yutou.qqbot.gpt.BaiduGPTManager;
import com.yutou.qqbot.interfaces.DownloadInterface; import com.yutou.qqbot.interfaces.DownloadInterface;
import com.yutou.qqbot.models.Model; import com.yutou.qqbot.models.Model;
import com.yutou.qqbot.utlis.HttpTools; import com.yutou.qqbot.utlis.HttpTools;
@ -202,6 +203,7 @@ public class GetSeTu extends Model {
} }
JSONObject item = json.getJSONArray("data").getJSONObject(0); JSONObject item = json.getJSONArray("data").getJSONObject(0);
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("标题:");
builder.append(item.getString("title")); builder.append(item.getString("title"));
builder.append("\n"); builder.append("\n");
builder.append("P站ID:"); builder.append("P站ID:");
@ -218,10 +220,18 @@ public class GetSeTu extends Model {
for (Object tags : item.getJSONArray("tags")) { for (Object tags : item.getJSONArray("tags")) {
builder.append(tags).append(""); builder.append(tags).append("");
} }
String gpt = """
你的人设傲娇萝莉
需求你在群组里有用户向你要擦边图片你需要根据返回的信息整理出文案输出一段话可以害羞也可以傲娇信息中包含了是否是R18的tag可以根据这个加大力度
输出说明不要输出任何提示词不要输出风格类型因为该输出是直接作用于显示的
图片信息[%s]
""";
gpt = BaiduGPTManager.getManager().sendTmpMessage("user", String.format(gpt, builder.toString()), "ernie-lite-8k").getContent();
builder.append("\n看不到图?点这里:").append(item.getJSONObject("urls").getString("regular")); builder.append("\n看不到图?点这里:").append(item.getJSONObject("urls").getString("regular"));
QQBotManager.getInstance().sendMessage(false, qq, QQBotManager.getInstance().sendMessage(false, qq,
new Reply(event.getMessageId()), new Reply(event.getMessageId()),
new Text(builder.toString()) new Text(builder.toString()),
new Text(gpt)
); );
HttpTools.download(item.getJSONObject("urls").getString("regular"), HttpTools.download(item.getJSONObject("urls").getString("regular"),
System.currentTimeMillis() + ".png", System.currentTimeMillis() + ".png",