目录
一、说明
我们在登录chatgpt官网进行对话是不收费的,但需要魔法。在调用官网的API时,在代码层面上使用,通过API KEY进行对话是收费的,不过刚注册的小伙伴有免费5美金的体验额度,在不调用绘画模型,只是做为简单的问答,个人使用是没问题的。
二、代码
2.1、对话测试
Gpt35TurboVO
java
import lombok.Data;
@Data
public class Gpt35TurboVO {
private String role; // 角色一般为 user
private String content; // 询问内容
}
Controller
java
@GetMapping(value = "/test", produces = "text/event-stream;charset=UTF-8")
public String test(@RequestParam String message) {
//回复用户
String apikey = "sk-****";
//请求ChatGPT的URL
String url = "https://api.openai.com/v1/chat/completions";
Gpt35TurboVO gpt35TurboVO = new Gpt35TurboVO();
gpt35TurboVO.setRole("user");
gpt35TurboVO.setContent(message);
List<Gpt35TurboVO> objects = new ArrayList<>();
objects.add(gpt35TurboVO);
Map<Object, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("model", "gpt-3.5-turbo"); //使用的模型
objectObjectHashMap.put("messages", objects); //提问信息
objectObjectHashMap.put("stream", false); //流
objectObjectHashMap.put("temperature", 0); //GPT回答温度(随机因子)
objectObjectHashMap.put("frequency_penalty", 0); //重复度惩罚因子
objectObjectHashMap.put("presence_penalty", 0.6); //控制主题的重复度
String postData = JSONUtil.toJsonStr(objectObjectHashMap);
String result2 = HttpRequest.post(url)
.header("Authorization", "Bearer " + apikey)//头信息,多个头信息多次调用此方法即可
.header("Content-Type", "application/json")
.body(postData)//表单内容
.timeout(200000)//超时,毫秒
.execute().body();
System.out.println(result2);
return result2;
}
返回结果
2.2、单次对话
ChatBotSingleQuestionVO
java
import lombok.Data;
/**
* 应用管理-单次提问-VO
* @author lf
* @date 2023/8/18
*/
@Data
public class ChatBotSingleQuestionVO {
/**
* 用户输入的询问内容
*/
private String prompt;
/**
* 角色扮演ID
*/
private Integer rolePlayId;
}
Redis锁工具类
java
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* redis锁工具类
*
* @author ruoyi
*/
@Component
public class RedisLock {
@Autowired
private RedissonClient redissonClient;
/**
* 获取锁
*
* @param lockKey 锁实例key
* @return 锁信息
*/
public RLock getRLock(String lockKey) {
return redissonClient.getLock(lockKey);
}
/**
* 加锁
*
* @param lockKey 锁实例key
* @return 锁信息
*/
public RLock lock(String lockKey) {
RLock lock = getRLock(lockKey);
lock.lock();
return lock;
}
/**
* 加锁
*
* @param lockKey 锁实例key
* @param leaseTime 上锁后自动释放锁时间
* @return true=成功;false=失败
*/
public Boolean tryLock(String lockKey, long leaseTime) {
return tryLock(lockKey, 0, leaseTime, TimeUnit.SECONDS);
}
/**
* 加锁
*
* @param lockKey 锁实例key
* @param leaseTime 上锁后自动释放锁时间
* @param unit 时间颗粒度
* @return true=加锁成功;false=加锁失败
*/
public Boolean tryLock(String lockKey, long leaseTime, TimeUnit unit) {
return tryLock(lockKey, 0, leaseTime, unit);
}
/**
* 加锁
*
* @param lockKey 锁实例key
* @param waitTime 最多等待时间
* @param leaseTime 上锁后自动释放锁时间
* @param unit 时间颗粒度
* @return true=加锁成功;false=加锁失败
*/
public Boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
RLock rLock = getRLock(lockKey);
boolean tryLock = false;
try {
tryLock = rLock.tryLock(waitTime, leaseTime, unit);
} catch (InterruptedException e) {
return false;
}
return tryLock;
}
/**
* 释放锁
*
* @param lockKey 锁实例key
*/
public void unlock(String lockKey) {
RLock lock = getRLock(lockKey);
lock.unlock();
}
/**
* 释放锁
*
* @param lock 锁信息
*/
public void unlock(RLock lock) {
lock.unlock();
}
}
Controller
java
@PostMapping("/chatBotSingleQuestion/api")
public AjaxResult chatBotSingleQuestion(@RequestBody ChatBotSingleQuestionVO chatBotSingleQuestionVO) {
String answerContent = iChatBotSingleQuestionService.chatBotSingleQuestion(chatBotSingleQuestionVO);
return success("success", answerContent);
}
Impl
java
/**
* 应用管理-用户单次提问-不支持续问对话
* @param chatBotSingleQuestionVO
* @return
*/
@Override
@Transactional
public String chatBotSingleQuestion(ChatBotSingleQuestionVO chatBotSingleQuestionVO) {
if (Objects.isNull(chatBotSingleQuestionVO.getRolePlayId())){
throw new RuntimeException("参数不可为空");
}
String lockName = "QA_" + SecurityUtils.getUserId();
//回答的内容
String answerContent = "";
try{
RLock rLock = redisLock.getRLock(lockName);
boolean locked = rLock.isLocked();
if (locked) {
throw new RuntimeException("正在回复中...");
}
//对同一用户访问加锁
redisLock.lock(lockName);
this.chatBefore(chatBotSingleQuestionVO);
InputStream is = this.sendRequestBeforeChat(chatBotSingleQuestionVO);
String line = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
while ((line = reader.readLine()) != null) {
//首先对行数据进行处理
if (StrUtil.isNotBlank(line) &&
!StrUtil.equals(line, "event: answer") &&
!StrUtil.equals(line, "event: chatResponse") &&
!StrUtil.contains(line, "data: {\"quoteLen\"")) {
line = CollectionUtil.removeEmpty(StrUtil.split(line, "data: ")).get(0);
if (!StrUtil.contains(line, "[DONE]")) {
String oneWord = catchTextGpt(line);
if (StrUtil.isNotBlank(oneWord)) {
answerContent = answerContent + oneWord;
}
}
WebSocketService.sendInfo(line, SecurityUtils.getUserId() + "");
TimeUnit.MILLISECONDS.sleep(50);
}
}
//处理完了后将次条聊天记录进行记录
if (StrUtil.isNotBlank(answerContent)) {
//保存聊天记录
this.saveDialogueProcess(chatBotSingleQuestionVO, answerContent);
//更新提问次数
this.upddateAppModel(chatBotSingleQuestionVO);
}
is.close();
reader.close();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}finally {
redisLock.unlock(lockName);
}
return answerContent;
}
sendRequestBeforeChat方法
java
/**
* 这块为问询,不包含对话模式
*
* @param chatBotSingleQuestionVO
* @return
* @throws Exception
*/
@Transactional
public InputStream sendRequestBeforeChat(ChatBotSingleQuestionVO chatBotSingleQuestionVO) throws Exception {
InputStream in = null;
// 通知内容添加文本铭感词汇过滤
//其余错误见返回码说明
//正常返回0
//违禁词检测
this.disableWordCheck(chatBotSingleQuestionVO.getPrompt());
String apikeyRefresh = getOpenAiKey();
if (StrUtil.isBlank(apikeyRefresh)) {
throw new RuntimeException("无可用key");
}
List<Gpt35TurboVO> chatContext = this.getChatContext(chatBotSingleQuestionVO);
String requestUrl = iTbKeyManagerService.getproxyUrl();
Map<Object, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("model", "gpt-3.5-turbo");
objectObjectHashMap.put("messages", chatContext);
objectObjectHashMap.put("stream", true);
objectObjectHashMap.put("temperature", 0);
objectObjectHashMap.put("frequency_penalty", 0);
objectObjectHashMap.put("presence_penalty", 0.6);
String bodyJson = JSONUtil.toJsonStr(objectObjectHashMap);
URL url = new URL(requestUrl); // 接口地址
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Charset", "UTF-8");
urlConnection.setRequestProperty("Authorization", "Bearer " + apikeyRefresh);
urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
byte[] dataBytes = bodyJson.getBytes();
urlConnection.setRequestProperty("Content-Length", String.valueOf(dataBytes.length));
OutputStream os = urlConnection.getOutputStream();
os.write(dataBytes);
in = new BufferedInputStream(urlConnection.getInputStream());
os.flush();
os.close();
return in;
}
catchTextGpt方法
java
/**
* 处理单独打印的文字
*
* @param str
* @return
*/
public String catchTextGpt(String str) {
String choices = JsonUtil.parseMiddleData(str, "choices");
JSONArray jsonArray = JSONUtil.parseArray(choices);
String string = jsonArray.getByPath("[0].delta").toString();
String content = JsonUtil.parseMiddleData(string, "content");
return content;
}
getChatContext方法
java
/**
* 角色扮演
* @param chatBotSingleQuestionVO
* @return 结果
*/
public List<Gpt35TurboVO> getChatContext(ChatBotSingleQuestionVO chatBotSingleQuestionVO) {
List<Gpt35TurboVO> messages = new ArrayList<>();
//首先获取角色,设置默认角色
String default_role_content = iconfigService.selectConfigByKey("default_role");
if (StrUtil.isBlank(default_role_content)) {
default_role_content = "我是一个全能机器人,可以回答你任何问题";
}
TbAppModel tbAppModel = iTbAppModelService.selectTbAppModelById(Long.valueOf(chatBotSingleQuestionVO.getRolePlayId()));
if (!Objects.isNull(tbAppModel)){
default_role_content = tbAppModel.getAppModelContent();
}
//小程序专用
//是否通过微信小程序审核的设定语
String is_open_pass_wx_promt = iconfigService.selectConfigByKey("is_open_pass_wx_promt");
if (StrUtil.isNotBlank(is_open_pass_wx_promt) && !StrUtil.equals(is_open_pass_wx_promt, "0")) {
String pass_wx_promt = iconfigService.selectConfigByKey("pass_wx_promt");
default_role_content = default_role_content + "。并且你必须遵循:" + pass_wx_promt;
}
//设定系统所扮演的角色
Gpt35TurboVO gpt35TurboVOSys = new Gpt35TurboVO();
gpt35TurboVOSys.setRole("system");
gpt35TurboVOSys.setContent(default_role_content);
messages.add(gpt35TurboVOSys);
//最后查询用户最新询问的问题
Gpt35TurboVO gpt35TurboUser = new Gpt35TurboVO();
gpt35TurboUser.setRole("user");
gpt35TurboUser.setContent(chatBotSingleQuestionVO.getPrompt());
messages.add(gpt35TurboUser);
return messages;
}
getOpenAiKey方法
java
/**
* 查询key是否可用
* @return 结果
*/
public String getOpenAiKey() {
//模仿查到的key集合
TbKeyManager tbKeyManager = new TbKeyManager();
tbKeyManager.setIsUse(1);
//可用的key
List<TbKeyManager> tbKeyManagers = iTbKeyManagerService.selectTbKeyManagerList(tbKeyManager);
//判断是否key额度用完
if (CollectionUtil.isEmpty(tbKeyManagers) || tbKeyManagers.size() <= 0) {
throw new RuntimeException("key额度耗尽");
}
//获取第一个key,然后将第一个key存入缓存
String key = tbKeyManagers.get(0).getSecretKey();
redisTemplate.opsForValue().set("apikey", key);
//检查key
changeKey(tbKeyManagers.get(0));
return key;
}
2.3、连续对话
Controller
java
@PostMapping(value = "/chatBotNoId/api")
public AjaxResult continuousDialogue(@RequestBody StreamParametersVO streamParametersVO) {
String answerContent = iChatGtpService.continuousDialogueSocketStream(streamParametersVO);
return success("success", answerContent);
}
Impl
java
/**
* 用户直接发起连续对话,系统同意创建对话主题,用户不用手动新建主题
*
* @param streamParametersVO
*/
@Override
public String continuousDialogueSocketStream(StreamParametersVO streamParametersVO) {
//判断是否isNewOpen填写参数,表示是否先开对话
if (Objects.isNull(streamParametersVO.getIsNewOpen())) {
throw new RuntimeException("isNewOpen参数未填");
}
if (streamParametersVO.getIsNewOpen()) {
//新开对话,创建新的对话主题
tbModelTable = new TbModelTable();
//主题名称
tbModelTable.setModelName("Dialogue_" + SecurityUtils.getUserId() + "_" + DateTime.now());
//设置模板角色
if (Objects.nonNull(streamParametersVO.getDialogueRoleId())) {
tbModelTable.setId(Long.valueOf(streamParametersVO.getDialogueRoleId()));
} else {
tbModelTable.setId(1L);
}
tbDialogueMain = tbDialogueMainService.creatNewDig(tbModelTable);
} else {
//非新开对话,查询本次的对话主题
TbDialogueMain tbDialogueMainParam = new TbDialogueMain();
//设置模板角色
if (Objects.nonNull(streamParametersVO.getDialogueRoleId())) {
tbDialogueMainParam.setDialogueRoleId(Long.valueOf(streamParametersVO.getDialogueRoleId()));
} else {
tbDialogueMainParam.setDialogueRoleId(1L);
}
tbDialogueMainParam.setUserId(SecurityUtils.getUserId());
List<TbDialogueMain> tbDialogueMains = iTbDialogueMainService.selectTbDialogueMainList(tbDialogueMainParam);
if (CollectionUtil.isEmpty(tbDialogueMains)) {
//创建新的对话主题
tbModelTable = new TbModelTable();
//主题名称
tbModelTable.setModelName("Dialogue_" + SecurityUtils.getUserId() + "_" + DateTime.now());
//设置模板角色
tbModelTable.setId(Long.valueOf(streamParametersVO.getDialogueRoleId()));
tbDialogueMain = tbDialogueMainService.creatNewDig(tbModelTable);
} else {
tbDialogueMain = tbDialogueMains.get(0);
}
}
//设置对话ID
streamParametersVO.setDialogueId(tbDialogueMain.getId());
String lockName = "chat_" + SecurityUtils.getUserId();
//回答的内容
String answerContent = "";
try {
RLock rLock = redisLock.getRLock(lockName);
boolean locked = rLock.isLocked();
if (locked) {
throw new RuntimeException("正在回复中...");
}
//对同一用户访问加锁
redisLock.lock(lockName);
//进来做校验
TbDialogueMain tbDialogueMain = this.paramVerify(streamParametersVO);
String userId = SecurityUtils.getUserId() + "";
//将提问数据封装为流,并请求OpenAI的接口
InputStream inputStream = this.sendRequestBefore(streamParametersVO, tbDialogueMain);
String line = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
while ((line = reader.readLine()) != null) {
//首先对行数据进行处理
if (StrUtil.isNotBlank(line) &&
!StrUtil.equals(line, "event: answer") &&
!StrUtil.equals(line, "event: chatResponse") &&
!StrUtil.contains(line, "data: {\"quoteLen\"")) {
line = CollectionUtil.removeEmpty(StrUtil.split(line, "data: ")).get(0);
if (StrUtil.contains(line, "[DONE]")) {
} else {
String oneWord = catchTextGpt(line);
if (StrUtil.isNotBlank(oneWord)) {
answerContent = answerContent + oneWord;
}
}
WebSocketService.sendInfo(line, userId);
TimeUnit.MILLISECONDS.sleep(50);
}
}
//处理完了后,将此条聊天记录进行保存
if (StrUtil.isNotBlank(answerContent)) {
//保存聊天记录
this.saveDig(streamParametersVO, answerContent);
}
inputStream.close();
reader.close();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
} finally {
//解锁
redisLock.unlock(lockName);
//清除正在问话的标识
redisTemplate.delete(SecurityUtils.getUserId() + "");
}
return answerContent;
}
sendRequestBefore方法
java
/**
* 这块为 - 流对话模式的封装
*
* @param streamParametersVO
* @param tbDialogueMain
* @return
* @throws Exception
*/
@Transactional
public InputStream sendRequestBefore(StreamParametersVO streamParametersVO, TbDialogueMain tbDialogueMain) throws Exception {
InputStream in = null;
//提问内容
String prompt = streamParametersVO.getPrompt();
// 获取当前的用户
String userId = SecurityUtils.getUserId() + "";
Object o = redisTemplate.opsForValue().get(userId);
if (!Objects.isNull(o)) {
throw new RuntimeException("正在回复");
}
redisTemplate.opsForValue().set(userId, true, 30, TimeUnit.SECONDS);
if (StrUtil.isBlank(prompt)) {
throw new RuntimeException("输入内容为空");
}
// 通知内容添加文本铭感词汇过滤
// 其余错误见返回码说明
// 违禁词检测 正常返回0
this.disableWordCheck(prompt);
String apikeyRefresh = getOpenAiKey();
if (StrUtil.isBlank(apikeyRefresh)) {
throw new RuntimeException("无可用key");
}
//处理提问内容(指定系统角色+对话上下文+最新的提问内容)
List<Gpt35TurboVO> chatContext = this.getChatDigContext(streamParametersVO, tbDialogueMain);
String requestUrl = iTbKeyManagerService.getproxyUrl();
Map<Object, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("model", "gpt-3.5-turbo");
objectObjectHashMap.put("messages", chatContext);
objectObjectHashMap.put("stream", true);
objectObjectHashMap.put("temperature", 0);
objectObjectHashMap.put("frequency_penalty", 0);
objectObjectHashMap.put("presence_penalty", 0.6);
String bodyJson = JSONUtil.toJsonStr(objectObjectHashMap);
URL url = new URL(requestUrl); // 接口地址
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Charset", "UTF-8");
urlConnection.setRequestProperty("Authorization", "Bearer " + apikeyRefresh);
urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
byte[] dataBytes = bodyJson.getBytes();
urlConnection.setRequestProperty("Content-Length", String.valueOf(dataBytes.length));
OutputStream os = urlConnection.getOutputStream();
os.write(dataBytes);
in = new BufferedInputStream(urlConnection.getInputStream());
os.flush();
os.close();
return in;
}
getChatDigContext方法
java
/**
* 获取对话上下文
*
* @param streamParametersVO
* @return
*/
public List<Gpt35TurboVO> getChatDigContext(StreamParametersVO streamParametersVO, TbDialogueMain tbDialogueMain) {
List<Gpt35TurboVO> messages = new ArrayList<>();
//首先获取角色,默认角色
String default_role_content = iconfigService.selectConfigByKey("default_role");
if (StrUtil.isBlank(default_role_content)) {
default_role_content = "我是一个全能机器人,可以回答你任何问题";
}
//根据用户传递过来的Id查询角色模型数据
TbModelTable tbModelTable = iTbModelTableService.selectTbModelTableById(tbDialogueMain.getDialogueRoleId());
if (!Objects.isNull(tbModelTable)) {
default_role_content = tbModelTable.getModelContent();
}
//小程序专用
//是否通过微信小程序审核的设定语
String is_open_pass_wx_promt = iconfigService.selectConfigByKey("is_open_pass_wx_promt");
if (StrUtil.isNotBlank(is_open_pass_wx_promt) && !StrUtil.equals(is_open_pass_wx_promt, "0")) {
String pass_wx_promt = iconfigService.selectConfigByKey("pass_wx_promt");
default_role_content = default_role_content + "。并且你必须遵循:" + pass_wx_promt;
}
//设定系统所扮演的角色
Gpt35TurboVO gpt35TurboVOSys = new Gpt35TurboVO();
gpt35TurboVOSys.setRole("system");
gpt35TurboVOSys.setContent(default_role_content);
messages.add(gpt35TurboVOSys);
//然后查询当前对话的上下文数据TbDialogueProcess
TbDialogueProcess tbDialogueProcess = new TbDialogueProcess();
tbDialogueProcess.setSessionId(streamParametersVO.getDialogueId());
tbDialogueProcess.setUserId(SecurityUtils.getUserId());
String default_context_num = iconfigService.selectConfigByKey("default_context_num");
if (StrUtil.isBlank(default_context_num) || !NumberUtil.isNumber(default_context_num)) {
default_context_num = "10";
}
tbDialogueProcess.setLimitNum(Integer.valueOf(default_context_num));
//根据对话ID和用户ID查询到对话列表-根据时间倒叙获取后几条设定的数据
List<TbDialogueProcess> tbDialogueProcessesDesc = iTbDialogueProcessService
.selectTbDialogueProcessListByLimitDesc(tbDialogueProcess);
if (CollectionUtil.isNotEmpty(tbDialogueProcessesDesc)) {
//获取到倒数10条数据后将数据正序配好
List<TbDialogueProcess> tbDialogueProcesses = tbDialogueProcessesDesc
.stream()
.sorted(Comparator.comparing(TbDialogueProcess::getCreateTime))
.collect(Collectors.toList());
for (TbDialogueProcess tbDialogueProcessfor : tbDialogueProcesses) {
Gpt35TurboVO gpt35TurboUser = new Gpt35TurboVO();
//用户询问的问题
gpt35TurboUser.setRole("user");
gpt35TurboUser.setContent(tbDialogueProcessfor.getAskContent());
messages.add(gpt35TurboUser);
//机器人回答的问题
Gpt35TurboVO gpt35TurAssistant = new Gpt35TurboVO();
gpt35TurAssistant.setRole("assistant");
gpt35TurAssistant.setContent(tbDialogueProcessfor.getAnswerContent());
messages.add(gpt35TurAssistant);
}
}
//最后查询用户最新询问的问题
Gpt35TurboVO gpt35TurboUser = new Gpt35TurboVO();
gpt35TurboUser.setRole("user");
gpt35TurboUser.setContent(streamParametersVO.getPrompt());
messages.add(gpt35TurboUser);
return messages;
}
2.4、AI绘画
Controller
java
@PostMapping("/image/api")
public AjaxResult imageApi(@RequestBody StreamImageParametersVO streamImageParametersVO) {
String answerContent = iChatGptImageService.imageSocketStream(streamImageParametersVO);
return success("success",answerContent);
}
Impl
java
@Override
public String imageSocketStream(StreamImageParametersVO imageParametersVO) {
String lockName = "image_" + SecurityUtils.getUserId();
String answerContent = "";
try{
RLock rLock = redisLock.getRLock(lockName);
boolean locked = rLock.isLocked();
if (locked){
throw new RuntimeException("回复中");
}
//对同一用户访问加锁
redisLock.lock(lockName);
//校验是否输入内容,次数扣减
this.imageBefore(imageParametersVO);
String userId = SecurityUtils.getUserId() + "";
InputStream is = this.sendRequestBeforeImage(imageParametersVO);
String line = null;
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
while((line = reader.readLine()) != null){
//数据处理
if (StrUtil.isNotBlank(line) &&
!StrUtil.equals(line, "event: answer") &&
!StrUtil.equals(line, "event: chatResponse") &&
!StrUtil.contains(line, "data: {\"quoteLen\"")) {
line = CollectionUtil.removeEmpty(StrUtil.split(line, "data: ")).get(0);
if (StrUtil.contains(line, "[DONE]")){
}else{
String oneWord = catchUrlImage(line);
if (StrUtil.isNotBlank(oneWord)){
answerContent = answerContent + oneWord;
}
}
WebSocketService.sendInfo(line,userId);
TimeUnit.MILLISECONDS.sleep(50);
}
}
//处理完之后将次条聊天记录进行记录
if (StrUtil.isNotBlank(answerContent)){
//保存聊天记录
this.saveDialogueLog(imageParametersVO, answerContent);
}
is.close();
reader.close();
}catch (Exception e){
throw new RuntimeException(e.getMessage());
}finally {
//解锁
redisLock.unlock(lockName);
redisTemplate.delete(SecurityUtils.getUserId() + "");
}
return saveImageUrl(jsonImageUrl(answerContent));
}
sendRequestBeforeImage方法
java
/**
* 问询,不包含对话模式
*/
@Transactional
public InputStream sendRequestBeforeImage(StreamImageParametersVO imageParametersVO) throws Exception{
InputStream in = null;
//通知内容添加文本敏感词汇过滤
//其余错误见返回码说明
//正常返回0
//违禁词检测
this.disbleWordImageCheck(imageParametersVO.getPrompt());
String apikeyRefresh = getOpenAiKey();
if (StrUtil.isBlank(apikeyRefresh)){
throw new RuntimeException("无可用key");
}
// List<Gpt35TurboVO> imageContext = this.getImageContext(imageParametersVO);
String requestImageUrl = iTbKeyManagerService.getImageProxyUrl();
Map<Object, Object> objectObjecHashtMap = new HashMap<>();
objectObjecHashtMap.put("prompt", imageParametersVO.getPrompt());
objectObjecHashtMap.put("n", 1);
objectObjecHashtMap.put("size", "1024x1024");
String bodyJson = JSONUtil.toJsonStr(objectObjecHashtMap);
URL url = new URL(requestImageUrl); //接口地址
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Charset", "UTF-8");
urlConnection.setRequestProperty("Authorization", "Bearer " + apikeyRefresh);
urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
byte[] dataBytes = bodyJson.getBytes();
urlConnection.setRequestProperty("Content-Length", String.valueOf(dataBytes.length));
OutputStream os = urlConnection.getOutputStream();
os.write(dataBytes);
in = new BufferedInputStream(urlConnection.getInputStream());
os.flush();
os.close();
return in;
}
catchUrlImage方法
java
/**
* 对链接地址处理
*/
public String catchUrlImage(String str){
return str;
}
图片处理,chatgpt返回的图片有效期是五分钟,我们需要将图片下载至本地或服务器。
java
/**
* 保存图片返回的结果
*/
public String saveImageUrl(String jsonUrl){
String imageURL = uploadFileImageAi(jsonUrl);
// 找到下划线的索引位置
int underscoreIndex = imageURL.indexOf('_');
String result = "";
if (underscoreIndex != -1) {
// 截取从下划线的位置开始到字符串的末尾
result = imageURL.substring(underscoreIndex - 9);
} else {
throw new RuntimeException("图片链接截取失败");
}
return TomcatConfig.getImageAiUrl() + "/" + result;
}
/**
* 图片处理
* @param imageUrl
* @return
*/
public String uploadFileImageAi(String imageUrl){
// //服务器文件上传路径
String path = TomcatConfig.setUploadImageAiUrl() + Constants.DRAW_PREFIX + "_" + Seq.getId(Seq.uploadSeqType) + ".png";
// 本地文件上传路径
// String path = "D:\\BaiduNetdiskDownload\\image-use\\" + Constants.DRAW_PREFIX + "_" + Seq.getId(Seq.uploadSeqType) + ".png";
try{
URL url = new URL(imageUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = connection.getInputStream();
OutputStream outputStream = new FileOutputStream(path);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
} else {
throw new RuntimeException("文件无法下载");
}
}catch (IOException e){
e.printStackTrace();
}
return path;
}
/**
* JSON数据处理
* @param imageContent
* @return
*/
public String jsonImageUrl(String imageContent){
//解析json字符串
JSONObject obj = JSON.parseObject(imageContent);
//获取 "data"字段相应的JSON数组
JSONArray dataArray = obj.getJSONArray("data");
//获取第一个元素路径地址
JSONObject dataObject = dataArray.getJSONObject(0);
// 返回"url"字段的值
return dataObject.getString("url");
}