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),双指针总计最多…...
IIC协议详解
目录 1.IIC协议概述 2.IIC总线传输 3.IIC-51单片机应用 1.起始信号 2.终止信号 3.应答信号 4.数据发送 4.IIC-32单片机应用 用到的库函数: 1.IIC协议概述 IIC全称Inter-Integrated Circuit (集成电路总线)是由PHILIPS公司在80年代开发的两线式串行总线&…...
element ui-表头自定义提示框
版本 “element-ui”: “^2.15.5”,需求:鼠标悬浮到该列表头,显示提示框代码 <el-table:data"xxxx"><el-table-column label"序号" width"40" type"index" /><el-table-columnv-for"(ite…...
Python 图形化界面基础篇:创建顶部菜单
Python 图形化界面基础篇:创建顶部菜单 引言 Tkinter 库简介步骤1:导入 Tkinter 模块步骤2:创建 Tkinter 窗口步骤3:创建顶部菜单栏步骤4:处理菜单项的点击事件步骤5:启动 Tkinter 主事件循环 完整示例代码…...
java实现十大排序算法
文章目录 冒泡排序选择排序插入排序希尔排序归并排序快速排序堆排序桶排序基数排序计数排序验证各个排序的时间复杂度和空间复杂度 冒泡排序 冒泡排序(Bubble Sort)是一种简单的比较排序算法,它的基本思想是重复地交换相邻的两个元素&#x…...
Linux日志管理-logrotate(crontab定时任务、Ceph日志转储)
文章目录 一、logrotate概述二、logrotate基本用法三、logrotate运行机制logrotate参数 四、logrotate是怎么做到滚动日志时不影响程序正常的日志输出呢?Linux文件操作机制方案一方案二 五、logrotate实战--Ceph日志转储参考 一、logrotate概述 logrotate是一个用于…...
用PHP异步协程控制python爬虫脚本,实现多协程分布式爬取
背景 公司需要爬取指定网站的产品数据。但是个人对python的多进程和协程不是特别熟悉。所以,想通过php异步协程,发起爬取url请求控制python爬虫脚本,达到分布式爬取的效果。 准备 1.准备一个mongodb数据库用于存放爬取数据2.引入flask包&a…...
VUE3写后台管理(3)
VUE3写后台管理(3) 1.环境1.node2.vite3.Element-plus4.vue-router5.element icon6.less7.vuex8.vue-demi9.mockjs10.axios11.echarts 2.首页1.布局Main2.头部导航栏CommonHeader3.左侧菜单栏CommonLeft4.首页Home1.从后端获取数据显示到前端table的三种…...
机器学习笔记之最优化理论与算法(十二)无约束优化问题——共轭梯度法
机器学习笔记之最优化理论与方法——共轭梯度法 引言回顾:共轭方向法的重要特征线性共轭梯度法共轭方向公式的证明过程 关于线搜索公式中参数的化简关于线搜索公式中步长部分的化简关于线搜索公式中共轭方向系数的化简参数化简的目的 非线性共轭梯度法(FR,PRP方法)关…...
JVM中的java同步互斥工具应用演示及设计分析
1.火车站售票系统仿真 某火车站目前正在出售火车票,共有50张票,而它有3个售票窗口同时售票,下面设计了一个程序模拟该火车站售票,通过实现Runnable接口实现(模拟网络延迟)。 伪代码: Ticket类…...
数据治理-数据质量
实现数据质量的前提就是数据本身是可靠和可信的。 导致数据质量低下的因素 组织缺乏对低质量数据影响的理解,缺乏规划、孤岛式系统设计、不一致的开发过程、不完整的文档、缺乏标准或缺乏治理等。 所有组织都会遇到与数据质量有关的问题。数据质量需要跨职能的承诺…...
wordpress修改html/有哪些免费推广网站
Class对象是没办法用new关键字得到的,因为它是jvm生成用来保存对应类的信息的,换句话说,当我们定义好一个类文件并编译成.class字节码后,编译器同时为我们创建了一个Class对象并将它保存.class文件中。我不知道这样描述是否妥当,因…...
南宁网站制作-中国互联/优化设计官方电子版
安装前先关闭杀毒软件和360卫士,注意安装路径不能有中文,安装包路径也不要有中文。[安装环境]:Win7/Win8/Win101.鼠标右击【VMware 15.5.0】压缩包选择【解压到VMware 15.5.0】。2.双击打开解压后的【VMware 15.5.0】文件夹。3.鼠标右击【VMw…...
asp企业营销型网站建设/杭州网站推广平台
在url地址栏传参数如果我们直接使用汉字可能有朋友会发现接受到的是乱码了或在搜索引擎过去都变乱了,下面我们来看看正确的jsp中页面间传汉字参数转码方法。转码:a.href"./showCont.jsp?tcontent" encodeURI(encodeURI(tcontent));解码&#…...
阳江保安招聘网/南宁seo规则
这几天电脑实验室坏了。。。。emmm,每次想好好做东西的时候,电脑就坏掉。。这次是连不上网,然后尝试修复之后,把pycharm也成功搞坏。。。。very good!!! 好吧,我用笔记本行了吧。。结果在笔记本上安装mysqlclient包时又…...
水果网站建设策划书/关键词seo排名怎么选
Vector中的resize()与reserve()的区别 我用的是VS2013编译器首先申明resize()和reserve()这两个成员函数都是Vector的公有成员函数(public member function)一、先了解vector容器的基本构成: 1.首先明白vector是一种顺序容器(申请的内部空间…...
沧州网站建设制作设计优化/石家庄新闻网头条新闻
chrome操作技巧: CtrlShiftI 开发人员工具CtrlShiftJ JavaScript 控制台CtrlShiftDel 清除浏览数据CtrlU 查看源代码ShiftEscape 查看任务管理器ctrlshiftB 可以悬挂或收起标签栏altF或者altE 可以打开您在chrome的设置菜单输入一个网址,然后按住Altenter键…...