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官网进行对话是不收费的,但需要魔法。在调用官网的API时,在代码层面上使用,通过API KEY进行对话是收费的,不过刚…...

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

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

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

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

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

【Linux学习】01Linux初识与安装
Linux(B站黑马)学习笔记 01Linux初识与安装 文章目录 Linux(B站黑马)学习笔记前言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序列化时,Spring框架会在需要将Java对象转换为JSON字符串时调用JsonSerializer。这通常发生在控制器方法返回JSON响应时,或者在将对象保存到数据库等操作中。 // 注册…...

Lostash同步Mysql数据到ElasticSearch(二)logstash脚本配置和常见坑点
1. logstash脚本编写(采用单文件对应单表实例) 新建脚本文件夹 cd /usr/local/logstash mkdir sql & cd sql vim 表名称.conf #如: znyw_data_gkb_logstash.conf 建立文件夹,保存资源文件更新Id mkdir -p /data/logstash/data/last_r…...

兔兔答题企业版1.0.0版本全网发布,同时开源前端页面到unicloud插件市场
项目说明 兔兔答题是用户端基于uniapp开发支持多端适配,管理端端采用TypeScriptVue3.jselement-plus,后端采用THinkPHP6PHP8Golang开发的一款在线答题应用程序。 问题反馈 线上预览地址 相关问题可以通过下方的二维码,联系到我。了解更多 …...

76、SpringBoot 整合 MyBatis------使用 sqlSession 作为 Dao 组件(就是ssm那一套,在 xml 写sql)
就是 ssm 那套,在xml 上面写sql ★ 基于SqlSession来实现DAO组件的方式 - MyBatis提供的Starter会自动在Spring容器中配置SqlSession(其实SqlSessionTemplate实现类)、并将它注入其他组件(如DAO组件)- DAO组件可直接…...
【ROS】RViz、Gazebo和Navigation的关系
1、RViz RViz(Robot Visualization,机器人可视化)是一个用于可视化机器人系统的开源工具,用于显示和调试机器人的传感器数据、状态信息和运动规划等。它是ROS(Robot Operating System)的一部分,是ROS中最常用的可视化工具之一。 RViz:“我们不生产数据只做数据的搬运…...

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

JavaWeb开发-06-SpringBootWeb-MySQL
一.MySQL概述 1.安装、配置 官网下载地址:https://dev.mysql.com/downloads/mysql/ 2.数据模型 3.SQL简介 二.数据库设计-DDL 1.数据库 官网:http:// https://www.jetbrains.com/zh-cn/datagrip/ 2.表(创建、查询、修改、删除) #…...
十六、垃圾回收相关概念
目录 一、System.gc()的理解二、内存溢出和内存泄漏2、内存泄漏 三、Stop the World1、什么是 stop the word ? 四、垃圾回收的并行和并发1、并发和并发2、垃圾回收的并行和并发 五、安全点与安全区域1、什么是安全点?2、安全区域 六、强引用(不可回收&…...

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

elasticsearch bulk 批量操作
1:bulk 是 elasticsearch 提供的一种批量增删改的操作API bulk 对 JSON串 有着严格的要求。每个JSON串 不能换行 ,只能放在同一行,同时, 相邻的JSON串之间必须要有换行 (Linux下是\n;Window下是\r\n&#…...
力扣11、 盛最多水的容器
方法一:双指针 考察: 贪心、数组、双指针 说明 本题是一道经典的面试题,最优的做法是使用「双指针」。如果读者第一次看到这题,不一定能想出双指针的做法。 复杂度分析 时间复杂度:O(N),双指针总计最多…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...