springboot+chatgpt+chatUI Pro開(kāi)發(fā)智能聊天工具的實(shí)踐
一、技術(shù)介紹
1.chatgpt-java是一個(gè)OpenAI的Java版SDK,支持開(kāi)箱即用。目前以支持官網(wǎng)全部Api。支持最新版本GPT-3.5-Turbo模型以及whisper-1模型。
2.Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來(lái)簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開(kāi)發(fā)過(guò)程。該框架使用了特定的方式來(lái)進(jìn)行配置,從而使開(kāi)發(fā)人員不再需要定義樣板化的配置。通過(guò)這種方式,Spring Boot致力于在蓬勃發(fā)展的快速應(yīng)用開(kāi)發(fā)領(lǐng)域(rapid application development)成為領(lǐng)導(dǎo)者。
3.ChatUI Pro 是在ChatUI 基礎(chǔ)組件的基礎(chǔ)上,結(jié)合阿里小蜜的最佳實(shí)踐,沉淀和總結(jié)出來(lái)的一個(gè)開(kāi)箱即用的,可快速搭建智能對(duì)話(huà)機(jī)器人的框架。它簡(jiǎn)單易上手,通過(guò)簡(jiǎn)單的配置就能搭建出對(duì)話(huà)機(jī)器人;同時(shí)它強(qiáng)大易擴(kuò)展,通過(guò)豐富的接口和自定義卡片滿(mǎn)足各種定制化需求。
二、項(xiàng)目介紹
本項(xiàng)目采用了GPT-3.5-Turb模型作為基礎(chǔ),通過(guò)springboot結(jié)合redis、chat-java以及chatUI Pro實(shí)現(xiàn)簡(jiǎn)單的人工智能機(jī)器人。因?yàn)樵L問(wèn)openAI的API返回結(jié)果比較慢,項(xiàng)目中當(dāng)前端將問(wèn)題請(qǐng)求發(fā)送到后端后,后端會(huì)將生成一個(gè)UUID,返回前端,同時(shí)后端也會(huì)重新開(kāi)啟一個(gè)線程去訪問(wèn)openAI,當(dāng)openAI返回結(jié)果后,后端將UUID做為key,openAI返回的結(jié)果做為value存儲(chǔ)到redis中。前端會(huì)根據(jù)后端第一次請(qǐng)求的結(jié)果中UUID做為參數(shù)每個(gè)5s請(qǐng)求一次后端的answer接口,answer接口會(huì)根據(jù)UUID查詢(xún)r(jià)edis是否有值,直到后端answer接口返回結(jié)果后前端將結(jié)果輸出給用戶(hù)
三、項(xiàng)目搭建
1.創(chuàng)建springboot項(xiàng)目,項(xiàng)目命名mychatgpt。
2.導(dǎo)入項(xiàng)目pom的依賴(lài)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.12</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.xyh</groupId> <artifactId>mychatgpt</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mychatgpt</name> <description>Demo project for Spring Boot</description> <properties> <java.version>8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <exclusions> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> </exclusion> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-to-slf4j</artifactId> </exclusion> </exclusions> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> </dependency> <dependency> <groupId>com.theokanning.openai-gpt3-java</groupId> <artifactId>api</artifactId> <version>0.10.0</version> </dependency> <dependency> <groupId>com.theokanning.openai-gpt3-java</groupId> <artifactId>service</artifactId> <version>0.10.0</version> </dependency> <dependency> <groupId>com.theokanning.openai-gpt3-java</groupId> <artifactId>client</artifactId> <version>0.10.0</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.12</version> </dependency> <dependency> <groupId>com.unfbx</groupId> <artifactId>chatgpt-java</artifactId> <version>1.0.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.17</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.8</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> <exclusions> <exclusion> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.github.yulichang</groupId> <artifactId>mybatis-plus-join</artifactId> <version>1.4.2</version> </dependency> <!--集成隨機(jī)生成數(shù)據(jù)包 --> <dependency> <groupId>com.apifan.common</groupId> <artifactId>common-random</artifactId> <version>1.0.19</version> </dependency> <!--集成隨機(jī)生成數(shù)據(jù)包 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
3.編寫(xiě)chatGPT實(shí)現(xiàn)工具類(lèi)
package com.xyh.mychatgpt.utils; import com.unfbx.chatgpt.OpenAiClient; import com.unfbx.chatgpt.entity.chat.ChatChoice; import com.unfbx.chatgpt.entity.chat.ChatCompletion; import com.unfbx.chatgpt.entity.chat.Message; import com.unfbx.chatgpt.entity.common.Choice; import com.unfbx.chatgpt.entity.completions.Completion; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; /** * @author xiangyuanhong * @description: TODO * @date 2023/3/21上午9:28 */ @Component public class ChatGPTUtils { @Value("${xyh.openai.key}") private String token; @Autowired private RedisUtils redisUtils; public void ask(String model,String question,String uuid){ StringBuffer result=new StringBuffer(); try { OpenAiClient openAiClient = new OpenAiClient(token, 3000, 300, 300, null); if("GPT-3.5-Turb".equals(model)){ // GPT-3.5-Turb模型 Message message=Message.builder().role(Message.Role.USER).content(question).build(); ChatCompletion chatCompletion = ChatCompletion.builder().messages(Arrays.asList(message)).build(); List<ChatChoice> resultList = openAiClient.chatCompletion(chatCompletion).getChoices(); for (int i = 0; i < resultList.size(); i++) { result.append(resultList.get(i).getMessage().getContent()); } }else{ //text-davinci-003/text-ada-003 Completion completion = Completion.builder() .prompt(question) .model(model) .maxTokens(2000) .temperature(0) .echo(false) .build(); Choice[] resultList = openAiClient.completions(completion).getChoices(); for (Choice choice : resultList) { result.append(choice.getText()); } } }catch (Exception e) { System.out.println(e.getMessage()); result.append("小愛(ài)還不太懂,回去一定努力學(xué)習(xí)補(bǔ)充知識(shí)"); } redisUtils.set(uuid,result.toString()); } }
4.開(kāi)發(fā)項(xiàng)目Controller類(lèi),用來(lái)與前端進(jìn)行交互
package com.xyh.mychatgpt.controller; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import com.xyh.mychatgpt.utils.ChatGPTUtils; import com.xyh.mychatgpt.utils.R; import com.xyh.mychatgpt.utils.RedisUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; /** * @author xiangyuanhong * @description: TODO * @date 2023/2/28下午4:57 */ @RestController public class IndexController { @Autowired private RedisUtils redisUtils; @Autowired private ChatGPTUtils chatGPTUtils; @GetMapping("/ask") public R ask(String question,HttpServletRequest request) { String uuid=IdUtil.simpleUUID(); if (StrUtil.isBlank(question)) { question = "今天天氣怎么樣?"; } String finalQuestion = question; ThreadUtil.execAsync(()->{ chatGPTUtils.ask("GPT-3.5-Turb", finalQuestion,uuid); }); return R.ok().put("data",uuid); } @GetMapping("/answer") public R answer(String uuid){ String result=redisUtils.get(uuid); return R.ok().put("data",result); } }
5.前端頁(yè)面開(kāi)發(fā),在項(xiàng)目templates目錄創(chuàng)建index.html頁(yè)面,并引入chatUI pro相關(guān)文件
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta name="renderer" content="webkit" /> <meta name="force-rendering" content="webkit" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0, viewport-fit=cover" /> <title>滴答小愛(ài)</title> <link rel="stylesheet" rel="external nofollow" > </head> <body> <div id="root"></div> <script src="http://g.alicdn.com/chatui/sdk-v2/0.2.4/sdk.js"></script> <script src="http://g.alicdn.com/chatui/extensions/0.0.7/isv-parser.js"></script> <script src="js/setup.js"></script> <script src="js/jquery-3.6.3.min.js"></script> <script src="http://g.alicdn.com/chatui/icons/0.3.0/index.js" async></script> </body> </html>
6.創(chuàng)建setup.js實(shí)現(xiàn)chatUI Pro與后端通信交換。
var bot = new ChatSDK({ config: { // navbar: { // title: '滴答小愛(ài)' // }, robot: { avatar: 'images/chat.png' }, // 用戶(hù)頭像 user: { avatar: 'images/user.png', }, // 首屏消息 messages: [ { type: 'text', content: { text: '您好,小愛(ài)為您服務(wù),請(qǐng)問(wèn)有什么可以幫您的?' } } ], // 快捷短語(yǔ) // quickReplies: [ // { name: '健康碼顏色',isHighlight:true }, // { name: '入浙通行申報(bào)' }, // { name: '健康碼是否可截圖使用' }, // { name: '健康通行碼適用范圍' }, // ], // 輸入框占位符 placeholder: '輸入任何您想詢(xún)問(wèn)的問(wèn)題', }, requests: { send: function (msg) { if (msg.type === 'text') { return { url: '/ask', data: { question: msg.content.text } }; } } }, handlers: { /** * * 解析請(qǐng)求返回的數(shù)據(jù) * @param {object} res - 請(qǐng)求返回的數(shù)據(jù) * @param {object} requestType - 請(qǐng)求類(lèi)型 * @return {array} */ parseResponse: function (res, requestType) { // 根據(jù) requestType 處理數(shù)據(jù) if (requestType === 'send' && res.code==0) { // 用 isv 消息解析器處理數(shù)據(jù) $.ajaxSettings.async=false; var answer=""; var isOK=false; while(!isOK){ $.get("/answer",{uuid:res.data},function(result){ console.log(result.data) if(null != result.data){ isOK=true; answer=result.data; } },"json"); if(!isOK){ sleep(5000); } } $.ajaxSettings.async=true; return [{"_id":res.data,type:"text",content:{text:answer},position:"left"}]; } }, }, }); function sleep(n) { //n表示的毫秒數(shù) var start = new Date().getTime(); while (true) { if (new Date().getTime() - start > n) { break; } } } bot.run();
7.項(xiàng)目搭建完成后啟動(dòng)springboot項(xiàng)目然后訪問(wèn)http://ip:端口就可以。項(xiàng)目最終效果:http://hyrun.vip/
四、項(xiàng)目展示
到此這篇關(guān)于springboot+chatgpt+chatUI Pro開(kāi)發(fā)智能聊天工具的實(shí)踐的文章就介紹到這了,更多相關(guān)springboot chatgpt智能聊天內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java內(nèi)部類(lèi)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
內(nèi)部類(lèi)是指在一個(gè)外部類(lèi)的內(nèi)部再定義一個(gè)類(lèi)。下面通過(guò)本文給大家java內(nèi)部類(lèi)的使用小結(jié),需要的朋友參考下吧2017-04-04SpringBoot動(dòng)態(tài)定時(shí)任務(wù)、動(dòng)態(tài)Bean、動(dòng)態(tài)路由詳解
這篇文章主要介紹了SpringBoot動(dòng)態(tài)定時(shí)任務(wù)、動(dòng)態(tài)Bean、動(dòng)態(tài)路由詳解,之前用過(guò)Spring中的定時(shí)任務(wù),通過(guò)@Scheduled注解就能快速的注冊(cè)一個(gè)定時(shí)任務(wù),但有的時(shí)候,我們業(yè)務(wù)上需要?jiǎng)討B(tài)創(chuàng)建,或者根據(jù)配置文件、數(shù)據(jù)庫(kù)里的配置去創(chuàng)建定時(shí)任務(wù),需要的朋友可以參考下2023-10-10Struts2實(shí)現(xiàn)文件上傳功能實(shí)例解析
這篇文章主要介紹了Struts2實(shí)現(xiàn)文件上傳功能實(shí)例解析,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-01-01基于MapReduce實(shí)現(xiàn)決策樹(shù)算法
這篇文章主要為大家詳細(xì)介紹了基于MapReduce實(shí)現(xiàn)決策樹(shù)算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08每日六道java新手入門(mén)面試題,通往自由的道路第二天
這篇文章主要為大家分享了最有價(jià)值的6道java面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,對(duì)hashCode方法的設(shè)計(jì)、垃圾收集的堆和代進(jìn)行剖析,感興趣的小伙伴們可以參考一下2021-06-06