当前位置: 首页 > news >正文

SpringBoot调用ChatGPT-API实现智能对话

目录

一、说明

二、代码

2.1、对话测试

2.2、单次对话

2.3、连续对话

2.4、AI绘画


一、说明

我们在登录chatgpt官网进行对话是不收费的,但需要魔法。在调用官网的API时,在代码层面上使用,通过API KEY进行对话是收费的,不过刚注册的小伙伴有免费5美金的体验额度,在不调用绘画模型,只是做为简单的问答,个人使用是没问题的。

ChatGPT官网

API使用情况

二、代码

2.1、对话测试

Gpt35TurboVO

import lombok.Data;@Data
public class Gpt35TurboVO {private String role;     // 角色一般为 userprivate String content;  // 询问内容
}

Controller

    @GetMapping(value = "/test", produces = "text/event-stream;charset=UTF-8")public String test(@RequestParam String message) {//回复用户String apikey = "sk-****";//请求ChatGPT的URLString 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

import lombok.Data;/*** 应用管理-单次提问-VO* @author lf* @date 2023/8/18*/
@Data
public class ChatBotSingleQuestionVO {/*** 用户输入的询问内容*/private String prompt;/*** 角色扮演ID*/private Integer rolePlayId;}

Redis锁工具类

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 {@Autowiredprivate 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

    @PostMapping("/chatBotSingleQuestion/api")public AjaxResult chatBotSingleQuestion(@RequestBody ChatBotSingleQuestionVO chatBotSingleQuestionVO) {String answerContent = iChatBotSingleQuestionService.chatBotSingleQuestion(chatBotSingleQuestionVO);return success("success", answerContent);}

Impl

    /*** 应用管理-用户单次提问-不支持续问对话* @param chatBotSingleQuestionVO* @return*/@Override@Transactionalpublic 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方法

    /*** 这块为问询,不包含对话模式** @param chatBotSingleQuestionVO* @return* @throws Exception*/@Transactionalpublic 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方法

    /*** 处理单独打印的文字** @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方法

    /*** 角色扮演* @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方法

    /*** 查询key是否可用* @return 结果*/public String getOpenAiKey() {//模仿查到的key集合TbKeyManager tbKeyManager = new TbKeyManager();tbKeyManager.setIsUse(1);//可用的keyList<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);//检查keychangeKey(tbKeyManagers.get(0));return key;}

2.3、连续对话

Controller

    @PostMapping(value = "/chatBotNoId/api")public AjaxResult continuousDialogue(@RequestBody StreamParametersVO streamParametersVO) {String answerContent = iChatGtpService.continuousDialogueSocketStream(streamParametersVO);return success("success", answerContent);}

Impl

    /*** 用户直接发起连续对话,系统同意创建对话主题,用户不用手动新建主题** @param streamParametersVO*/@Overridepublic 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);}}//设置对话IDstreamParametersVO.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方法

    /*** 这块为 - 流对话模式的封装** @param streamParametersVO* @param tbDialogueMain* @return* @throws Exception*/@Transactionalpublic 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("输入内容为空");}// 通知内容添加文本铭感词汇过滤// 其余错误见返回码说明// 违禁词检测 正常返回0this.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方法

    /*** 获取对话上下文** @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);//然后查询当前对话的上下文数据TbDialogueProcessTbDialogueProcess 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

    @PostMapping("/image/api")public AjaxResult imageApi(@RequestBody StreamImageParametersVO streamImageParametersVO) {String answerContent = iChatGptImageService.imageSocketStream(streamImageParametersVO);return success("success",answerContent);}

Impl

    @Overridepublic 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方法

    /*** 问询,不包含对话模式*/@Transactionalpublic 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方法

    /*** 对链接地址处理*/public String catchUrlImage(String str){return str;}

图片处理,chatgpt返回的图片有效期是五分钟,我们需要将图片下载至本地或服务器。

    /*** 保存图片返回的结果*/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");}

 

 

 

相关文章:

SpringBoot调用ChatGPT-API实现智能对话

目录 一、说明 二、代码 2.1、对话测试 2.2、单次对话 2.3、连续对话 2.4、AI绘画 一、说明 我们在登录chatgpt官网进行对话是不收费的&#xff0c;但需要魔法。在调用官网的API时&#xff0c;在代码层面上使用&#xff0c;通过API KEY进行对话是收费的&#xff0c;不过刚…...

element-table出现错位解决方法

先看示例图&#xff0c;这个在开发中还是很常遇到的&#xff0c;在table切换不同数据时或者切换页面时&#xff0c;容易出现&#xff1a; 解决方法很简单&#xff0c;官方有提供方法&#xff1a; 我们可以在重新渲染数据后&#xff1a; this.$nextTick(() > {this.$refs.…...

DC电源模块具有不同的安装方式和安全规范

BOSHIDA DC电源模块具有不同的安装方式和安全规范 DC电源模块是将低压直流电转换为需要的输出电压的装置。它们广泛应用于各种领域和行业&#xff0c;如通信、医疗、工业、家用电器等。安装DC电源模块应严格按照相关的安全规范进行&#xff0c;以确保其正常运行和安全使用。 D…...

zabbix自定义监控、钉钉、邮箱报警

目录 一、实验准备 二、安装 三、添加监控对象 四、添加自定义监控项 五、监控mariadb 1、添加模版查看要求 2、安装mariadb、创建用户 3、创建用户文件 4、修改监控模版 5、在上述文件中配置路径 6、重启zabbix-agent验证 六、监控NGINX 1、安装NGINX&#xff0c…...

短信、邮箱验证码本地可以,部署到服务器接口却不能使用

应对公司双验证要求&#xff0c;对本系统做邮箱、短信验证码登录&#xff0c;本地开发正常发送&#xff0c;到服务器上部署却使用失败&#xff0c;已全部解决&#xff0c;记录坑。 一、nginx拦截 先打开你的服务器 nginx.conf 看看有没有做接口拦截。&#xff08;本地可能做Sp…...

Java web基础知识

Servlet Servlet是sun公司开发的动态web技术 sun在API中提供了一个接口叫做 Servlet &#xff0c;一个简单的Servlet 程序只需要完成两个步骤 编写一个实现了Servlet接口的类 把这个Java部署到web服务器中 一般来说把实现了Servlet接口的java程序叫做&#xff0c;Servlet 初步…...

【Linux学习】01Linux初识与安装

Linux&#xff08;B站黑马&#xff09;学习笔记 01Linux初识与安装 文章目录 Linux&#xff08;B站黑马&#xff09;学习笔记前言01Linux初识与安装操作系统简述Linux初识虚拟机介绍安装VMware Workstation虚拟化软件VMware中安装CentOS7 Linux操作系统下载CentOS操作系统VMwa…...

android 将数据库中的 BLOB 对象动态加载为 XML,并设置到 Android Activity 的内容视图上

以下是一个示例代码,演示如何将数据库中的 BLOB 对象动态加载为 XML,并设置到 Android Activity 的内容视图上: ```java import android.app.Activity; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import and…...

Android12之强弱智能指针sp/wp循环引用死锁问题(一百六十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…...

springboot自定义Json序列化返回,实现自动转换字典值

自定义序列化 原理 当你使用Spring Boot的Spring Data或者Spring MVC等组件来处理JSON序列化时&#xff0c;Spring框架会在需要将Java对象转换为JSON字符串时调用JsonSerializer。这通常发生在控制器方法返回JSON响应时&#xff0c;或者在将对象保存到数据库等操作中。 // 注册…...

Lostash同步Mysql数据到ElasticSearch(二)logstash脚本配置和常见坑点

1. logstash脚本编写&#xff08;采用单文件对应单表实例&#xff09; 新建脚本文件夹 cd /usr/local/logstash mkdir sql & cd sql vim 表名称.conf #如: znyw_data_gkb_logstash.conf 建立文件夹&#xff0c;保存资源文件更新Id mkdir -p /data/logstash/data/last_r…...

兔兔答题企业版1.0.0版本全网发布,同时开源前端页面到unicloud插件市场

项目说明 兔兔答题是用户端基于uniapp开发支持多端适配&#xff0c;管理端端采用TypeScriptVue3.jselement-plus&#xff0c;后端采用THinkPHP6PHP8Golang开发的一款在线答题应用程序。 问题反馈 线上预览地址 相关问题可以通过下方的二维码&#xff0c;联系到我。了解更多 …...

76、SpringBoot 整合 MyBatis------使用 sqlSession 作为 Dao 组件(就是ssm那一套,在 xml 写sql)

就是 ssm 那套&#xff0c;在xml 上面写sql ★ 基于SqlSession来实现DAO组件的方式 - MyBatis提供的Starter会自动在Spring容器中配置SqlSession&#xff08;其实SqlSessionTemplate实现类&#xff09;、并将它注入其他组件&#xff08;如DAO组件&#xff09;- DAO组件可直接…...

【ROS】RViz、Gazebo和Navigation的关系

1、RViz RViz(Robot Visualization,机器人可视化)是一个用于可视化机器人系统的开源工具,用于显示和调试机器人的传感器数据、状态信息和运动规划等。它是ROS(Robot Operating System)的一部分,是ROS中最常用的可视化工具之一。 RViz:“我们不生产数据只做数据的搬运…...

智能井盖:提升城市井盖安全管理效率

窨井盖作为城市基础设施的重要组成部分&#xff0c;其安全管理与城市的有序运行和群众的生产生活安全息息相关&#xff0c;体现城市管理和社会治理水平。当前&#xff0c;一些城市已经将智能化的窨井盖升级改造作为新城建的重要内容&#xff0c;推动窨井盖等“城市部件”配套建…...

JavaWeb开发-06-SpringBootWeb-MySQL

一.MySQL概述 1.安装、配置 官网下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 2.数据模型 3.SQL简介 二.数据库设计-DDL 1.数据库 官网&#xff1a;http:// https://www.jetbrains.com/zh-cn/datagrip/ 2.表&#xff08;创建、查询、修改、删除&#xff09; #…...

十六、垃圾回收相关概念

目录 一、System.gc()的理解二、内存溢出和内存泄漏2、内存泄漏 三、Stop the World1、什么是 stop the word ? 四、垃圾回收的并行和并发1、并发和并发2、垃圾回收的并行和并发 五、安全点与安全区域1、什么是安全点&#xff1f;2、安全区域 六、强引用&#xff08;不可回收&…...

hive、spark、presto 中的增强聚合-grouping sets、rollup、cube

目录 1、什么是增强聚合和多维分析函数&#xff1f; 2、grouping sets - 指定维度组合 3、with rollup - 上卷维度组合 4、with cube - 全维度组合 5、Grouping__ID、grouping() 的使用场景 6、使用 增强聚合 会不会对查询性能有提升呢&#xff1f; 7、对grouping sets、…...

elasticsearch bulk 批量操作

1&#xff1a;bulk 是 elasticsearch 提供的一种批量增删改的操作API bulk 对 JSON串 有着严格的要求。每个JSON串 不能换行 &#xff0c;只能放在同一行&#xff0c;同时&#xff0c; 相邻的JSON串之间必须要有换行 &#xff08;Linux下是\n&#xff1b;Window下是\r\n&#…...

力扣11、 盛最多水的容器

方法一&#xff1a;双指针 考察&#xff1a; 贪心、数组、双指针 说明 本题是一道经典的面试题&#xff0c;最优的做法是使用「双指针」。如果读者第一次看到这题&#xff0c;不一定能想出双指针的做法。 复杂度分析 时间复杂度&#xff1a;O(N)&#xff0c;双指针总计最多…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...