国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源

這篇具有很好參考價值的文章主要介紹了福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

簡介

本文分享一個我前幾個月實現(xiàn)的一個智能聊天系統(tǒng)小項目,包含了java后端,微信小程序端,web頁面端三個子工程。

代碼已經(jīng)全部開源,地址放在了文末。

最近一年,chatGPT的火爆程度,已經(jīng)不需要我再多說了,但是依舊有很多人想用卻用不上,原因大家也都很清楚,因為需要科學(xué)上網(wǎng)才可以訪問,并且注冊也需要綁定海外的銀行卡。那么這就給了很多人賺錢的機會,于是很多套殼類網(wǎng)站層出不窮,只需要簡單寫一下代碼,部署到海外的服務(wù)器上,就可以進行訪問了,并且可以實現(xiàn)和chatgpt官網(wǎng)一樣的效果。然后再通過充值會員,或者購買次數(shù),來賺錢。

當(dāng)然,我這個項目也是很久之前就已經(jīng)實現(xiàn)了,但是并不是為了賺錢,當(dāng)時的想法是,第一是為了練習(xí)編程技術(shù),作為程序員,遇到新鮮的事物,總是會想著嘗試一番。第二是為了方便自己,因為自己平時學(xué)習(xí)或者辦公中,也會經(jīng)常使用chatgpt,但是公司網(wǎng)絡(luò)又不允許我使用官網(wǎng),那么不如自己來套殼一個,然后再提供前端頁面進行交互,不就可以了嗎。

后來,因為網(wǎng)頁版對于手機使用非常不方便,于是就又開發(fā)出一個微信小程序,可以隨時隨地使用了,對我的工作和學(xué)習(xí)幫助還是挺大的,遇到問題就可以直接詢問chatGPT了,而且我預(yù)設(shè)置了多種角色,精心調(diào)試了prompt,來實現(xiàn)特定場景或特定領(lǐng)域的問答機器人。

現(xiàn)在,我決定將這些所有的東西全部開源,毫無保留,大家可以使用代碼進行學(xué)習(xí)或者部署使用,微信小程序端就不建議大家發(fā)布了,現(xiàn)在微信是不允許對接chatGPT的,大概率會審核不通過。我是因為發(fā)布的早,并且沒有做過宣傳,只是自己和身邊人使用,訪問量非常小。

效果圖展示

先來看下效果圖吧,這樣才能更加直觀的展示。vue實現(xiàn)的網(wǎng)頁端和微信小程序端,整體功能是一樣的,只是布局有一點小的差異。

網(wǎng)頁端

可以根據(jù)類別進行劃分,每個類別下有多種角色
福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源,chatgpt,chatgpt,小程序,開源
福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源,chatgpt,chatgpt,小程序,開源
聊天頁面,類似微信聊天一樣,左側(cè)是聯(lián)系人列表,右邊是對話框,下方是輸入框。對話框中,自己的輸入在右邊顯示,chatGPT的輸出在左邊顯示。支持markdown格式轉(zhuǎn)換。
福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源,chatgpt,chatgpt,小程序,開源福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源,chatgpt,chatgpt,小程序,開源

微信小程序端

類似的布局,同樣的功能,支持積分扣減
福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源,chatgpt,chatgpt,小程序,開源
福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源,chatgpt,chatgpt,小程序,開源

后端項目介紹

后端是使用spring boot進行搭建的, 同時會使用到mysql, mybaits,spring data jpa, redis等組件。

為什么使用spring boot,因為自己是一名java程序員,當(dāng)然對python和go也略知一二,只是對性能要求沒有那么高,并且自己根據(jù)熟悉,所以選擇了java語言,而Spring Boot是一個開源的Java開發(fā)框架,它簡化了Java應(yīng)用程序的開發(fā)和部署過程。相比于傳統(tǒng)的Java開發(fā),Spring Boot具有以下優(yōu)點:
1.簡化配置:Spring Boot提供了自動配置的功能,可以根據(jù)項目的依賴自動配置各種組件,無需手動編寫大量的XML配置文件,大大提高了開發(fā)效率。

2.內(nèi)嵌服務(wù)器:Spring Boot內(nèi)置了常用的服務(wù)器,如Tomcat、Jetty等,可以直接將應(yīng)用程序打包為可執(zhí)行的Jar包或War包,簡化了部署和運行的過程。

3.良好的擴展性:Spring Boot基于Spring框架,可以與其他Spring生態(tài)系統(tǒng)的組件無縫集成,如Spring Data、Spring Security等,拓展了開發(fā)的能力。

搭建Spring Boot項目環(huán)境非常簡單,只需要幾個步驟:

1.在IDE中創(chuàng)建一個新的Spring Boot項目,可以選擇使用Spring Initializr或者直接創(chuàng)建一個空的Maven或Gradle項目。

2.在項目的依賴管理文件(如pom.xml)中,添加Spring Boot的啟動器依賴,例如:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

3.編寫Spring Boot應(yīng)用程序的入口類,例如:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

4.在入口類中,可以添加一些配置和組件,例如定義數(shù)據(jù)源、配置日志等。

至此,一個簡單的Spring Boot項目就搭建完成了。接下來,我們將介紹如何集成OpenAI接口實現(xiàn)ChatGPT功能。

為了實現(xiàn)ChatGPT功能,我們需要先了解OpenAI接口的相關(guān)信息。OpenAI是一個人工智能技術(shù)公司,提供了各種自然語言處理的API,其中包括了ChatGPT功能。ChatGPT是一個強大的對話生成模型,可以根據(jù)輸入的對話歷史生成下一句話。

要使用OpenAI接口,我們需要進行以下步驟:

1.注冊O(shè)penAI賬號并獲取API密鑰:在OpenAI官網(wǎng)注冊一個賬號,并獲取API密鑰,用于進行API請求。

2.集成OpenAI接口到Spring Boot項目:添加OpenAI的API依賴到項目中,我這里使用的是另外一個開源項目chatgpt-java,例如:

 <dependency>
   <groupId>com.unfbx</groupId>
    <artifactId>chatgpt-java</artifactId>
    <version>1.0.12</version>
</dependency>

3.使用webSocket。
WebSocket是一種在客戶端和服務(wù)器之間實現(xiàn)雙向通信的協(xié)議,通過該協(xié)議可以在服務(wù)端主動向客戶端推送數(shù)據(jù),實現(xiàn)實時的雙向通信。與傳統(tǒng)的HTTP請求-響應(yīng)模式不同,WebSocket的連接一旦建立,客戶端和服務(wù)器可以持久性地保持連接,雙方可以隨時發(fā)送和接收消息,達到實時通信的效果。這種實時通信對于聊天應(yīng)用、實時數(shù)據(jù)展示和協(xié)同編輯等場景非常有用。
(1)添加依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

(2)建立連接,這里需要參數(shù)用戶id

 @OnOpen
 public void onOpen(Session session, @PathParam("uid") String uid) {
     log.info("websocket open,uid:{}", uid);
     this.session = session;
     this.uid = uid;
     webSocketSet.add(this);
     SESSIONS.add(session);

     if (chatWebSocketMap.containsKey(uid)) {
         chatWebSocketMap.remove(uid);
         chatWebSocketMap.put(uid, this);
     } else {
         chatWebSocketMap.put(uid, this);
         addOnlineCount();
     }
     log.info("websocket onOpen, userId:{}, online count:{}", this.uid, getOnlineCount());
 }

(3)接收前端消息,并調(diào)用openAI。

因為websocket只能有定義一個字符串進行前后端交互,所以如果我們需要傳遞多個參數(shù)的話,需要將其轉(zhuǎn)換為json字符串傳遞進來,并在接受后進行解析。如下所示,我們需要將roleId傳遞進來,roleId代表是和哪一個角色進行對話,這個在后面會用到,messages列表,里面存放了歷史對話記錄,這里傳遞進來是為了保持上下文進行通信,創(chuàng)建一個EventSourceListener,并把session傳入進去,最后ChatCompletion 就是與openAI交互的結(jié)構(gòu)體。

@OnMessage
public void onMessage(String message) {
     log.info("onMessage, userId:{} ", this.uid);
     JSONObject jsonObject = JSONUtil.parseObj(message);
     Integer roleId = jsonObject.getInt("roleId");
     String messageString = jsonObject.getStr("message");
     List<Message> messages = new ArrayList<>();
     messages = JSONUtil.toList(messageString, Message.class);
     //接受參數(shù)
     OpenAIWebSocketEventSourceListener eventSourceListener = new OpenAIWebSocketEventSourceListener(this.session);

     ChatCompletion chatCompletion = buildChatCompletion(roleId, messages);
     openAiStreamClient.streamChatCompletion(chatCompletion, eventSourceListener);
 }

(4)組裝報文。

我們可以將每一種角色的prompt,使用到的模型,最大token等參數(shù),保存到數(shù)據(jù)庫中,根據(jù)roleId進行獲取,然后組裝成ChatCompletion。其中,message結(jié)構(gòu)體中,包含了role和content,role分為三種,分別是system,user,assistant。其中system是系統(tǒng)指定的,里面可以存放你的prompt,用來告訴chatGPT,它現(xiàn)在要扮演什么角色,要怎么輸出內(nèi)容,都可以在system指令中進行指定。user為用戶輸入的文本。assistant為chatGPT的回答的文本。model中可以指定自己使用的模型,可以使用gpt-3.5-turbo,gpt-4-32k等,根據(jù)自己實際情況進行選擇。

private ChatCompletion buildChatCompletion(int id, List<Message> messages) {
     ChatCompletion chatCompletion;
     Role role = roleService.getRoleById(id);
     if (role != null) {
         Message roleMessage = Message.builder().content(role.getRoleMessage())
                 .role(Message.Role.SYSTEM).build();
         messages.add(0, roleMessage);
         chatCompletion = ChatCompletion.builder()
                 .temperature(role.getTemperature())
                 .model(role.getModel())
                 .maxTokens(role.getMaxTokens())
                 .topP(role.getTopP())
                 .presencePenalty(role.getPresencePenalty())
                 .frequencyPenalty(role.getFrequencyPenalty())
                 .messages(messages)
                 .stream(true)
                 .user(this.uid)
                 .build();
     } else {
         chatCompletion = ChatCompletion.builder()
                 .messages(messages)
                 .stream(true)
                 .user(this.uid)
                 .build();
     }
     return chatCompletion;
 }

(5)發(fā)送請求到openAI

public void streamChatCompletion(ChatCompletion chatCompletion, EventSourceListener eventSourceListener) {
    if (Objects.isNull(eventSourceListener)) {
        log.error("參數(shù)異常:EventSourceListener不能為空,可以參考:com.unfbx.chatgpt.sse.ConsoleEventSourceListener");
        throw new BaseException(CommonError.PARAM_ERROR);
    } else {
        if (!chatCompletion.isStream()) {
            chatCompletion.setStream(true);
        }

        try {
            EventSource.Factory factory = EventSources.createFactory(this.okHttpClient);
            ObjectMapper mapper = new ObjectMapper();
            String requestBody = mapper.writeValueAsString(chatCompletion);
            Request request = (new Request.Builder()).url(this.apiHost + "v1/chat/completions").post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), requestBody)).build();
            factory.newEventSource(request, eventSourceListener);
        } catch (JsonProcessingException var8) {
            log.error("請求參數(shù)解析異常:{}", var8);
            var8.printStackTrace();
        } catch (Exception var9) {
            log.error("請求參數(shù)解析異常:{}", var9);
            var9.printStackTrace();
        }

    }
}

上面代碼中,通過okHttpClient創(chuàng)建了一個EventSource.Factory對象,然后創(chuàng)建了一個ObjectMapper對象,用于將數(shù)據(jù)轉(zhuǎn)換為JSON格式。使用ObjectMapper將completion對象轉(zhuǎn)換為JSON字符串,存儲在requestBody變量中,使用ObjectMapper將completion對象轉(zhuǎn)換為JSON字符串,存儲在requestBody變量中,最后通過已創(chuàng)建的EventSource.Factory對象調(diào)用newEventSource方法,傳入創(chuàng)建的Request對象和eventSourceListener參數(shù)。這樣就創(chuàng)建了一個EventSource對象,并開始監(jiān)聽事件。簡單來說,這段代碼的作用是創(chuàng)建一個EventSource對象,并發(fā)送一個POST請求。

現(xiàn)在有兩項技術(shù)需要解釋一下,分別是okHttpClient和EventSource。

okHttpClient

okHttpClient是一個開源的Java HTTP客戶端庫,由Square公司開發(fā)。它提供了一個簡單易用的接口,用于發(fā)送HTTP請求并處理響應(yīng)。
特點:

  • 支持同步和異步請求:okHttpClient可以發(fā)送同步和異步的HTTP請求。同步請求會阻塞當(dāng)前線程,直到接收到服務(wù)器的響應(yīng);異步請求則使用回調(diào)函數(shù)來處理響應(yīng)。

  • 連接池管理:okHttpClient使用連接池來管理和復(fù)用HTTP連接,從而降低網(wǎng)絡(luò)請求的延遲。它支持并發(fā)請求和多線程環(huán)境下的高效連接復(fù)用。

  • 支持HTTP/2和SPDY協(xié)議:okHttpClient支持最新的HTTP/2和SPDY協(xié)議,可以提供更快的傳輸速度和更低的網(wǎng)絡(luò)延遲。

  • 支持攔截器:okHttpClient提供了攔截器機制,可以在請求和響應(yīng)的不同階段進行自定義操作,例如添加請求頭、日志記錄等。

  • 支持重試和重定向:okHttpClient可以自動處理請求的失敗、重試和重定向,減少開發(fā)者處理這些場景的工作量。

  • 可擴展性和靈活性:okHttpClient通過插件系統(tǒng)提供了很高的可擴展性,并且可以根據(jù)實際需求進行各種配置,如超時設(shè)置、緩存策略等。

總的來說,okHttpClient是一個功能強大、易于使用和高效的Java HTTP客戶端庫,用于發(fā)送HTTP請求并處理響應(yīng),適用于各種網(wǎng)絡(luò)場景和需求。

EventSource

EventSource是HTML5中定義的一種客戶端API,也被稱為服務(wù)器發(fā)送事件(Server-Sent Events)。它提供了一種在客戶端與服務(wù)器之間實現(xiàn)單向通信的機制。以下是EventSource的作用和詳細解釋:
作用:

  • 實時數(shù)據(jù)推送:EventSource可以與服務(wù)器建立長連接,通過服務(wù)器推送數(shù)據(jù),實現(xiàn)實時更新,而無需客戶端主動請求。

  • 可靠性:EventSource會自動恢復(fù)與服務(wù)器連接,即使網(wǎng)絡(luò)連接中斷或重新連接。

  • 簡化開發(fā):相比于WebSocket,EventSource更為簡單易用,不需要進行握手等繁瑣的操作。

工作原理:

  • 客戶端通過創(chuàng)建EventSource對象,并指定服務(wù)器端的URL來與服務(wù)器進行連接。

  • 服務(wù)器向客戶端發(fā)送事件流(event stream),可以包含不同類型的事件(event),每個事件都包含一個事件類型(event type)和事件數(shù)據(jù)(event data)。

  • 客戶端通過監(jiān)聽EventSource對象的相關(guān)事件來獲取服務(wù)器發(fā)來的數(shù)據(jù),如onmessage事件用于接收消息,onerror事件用于處理連接錯誤,等等。

優(yōu)點:

  • 對于服務(wù)器推送數(shù)據(jù)的場景非常適用,特別是在實時性要求較高且數(shù)據(jù)量較小的情況下。

  • 內(nèi)部自動處理了連接狀態(tài)、網(wǎng)絡(luò)中斷等問題,減輕了開發(fā)者的負擔(dān)。

  • 不需要考慮跨域問題,因為EventSource默認支持跨域訪問。

需要注意的是,EventSource與WebSocket的區(qū)別在于數(shù)據(jù)傳輸方式。WebSocket提供了雙向通信的能力,并支持客戶端和服務(wù)器端之間的全雙工通信,而EventSource只支持服務(wù)器向客戶端的單向數(shù)據(jù)推送。

我們這里后端代碼調(diào)用openAI使用的是EventSource,前端和后端通信用的是WebSocket,其實都可以使用EventSource。

(6)監(jiān)聽openAI響應(yīng)
我們通過EventSourceListener監(jiān)聽

public void onEvent(EventSource eventSource, String id, String type, String data) {
     if (data.equals("[DONE]")) {
         log.info("OpenAI返回數(shù)據(jù)結(jié)束了");
         session.getBasicRemote().sendText("[DONE]");
         return;
     }
     ObjectMapper mapper = new ObjectMapper();
     ChatCompletionResponse completionResponse = mapper.readValue(data, ChatCompletionResponse.class);
     String delta = mapper.writeValueAsString(completionResponse.getChoices().get(0).getDelta());
     session.getBasicRemote().sendText(delta);
 }

session對象代表了客戶端與服務(wù)器之間的一個會話連接。它是WebSocket中的一個核心對象,用于進行數(shù)據(jù)交互。session.getBasicRemote()方法返回RemoteEndpoint.Basic對象,通過該對象可以向客戶端發(fā)送消息。

sendText()方法是RemoteEndpoint.Basic對象的一個方法,用于發(fā)送文本消息到客戶端。delta是要發(fā)送的文本消息內(nèi)容。這句代碼的作用是將delta文本消息發(fā)送給客戶端,實現(xiàn)服務(wù)器向客戶端的實時消息推送功能,這樣,之前和后端建立好WebSocket連接的前端,就可以接收到來自chatGPT的響應(yīng)了。

數(shù)據(jù)庫結(jié)構(gòu)

主要涉及到3張表,分別為role_type,role_desc和role。其中,role_type表是存放角色分類的,如娛樂、生活、工作、學(xué)習(xí)、健康等。
建表語句如下:

CREATE TABLE `role_type` (
  `id` varchar(64) NOT NULL COMMENT '主鍵',
  `role_type_name` varchar(256) NOT NULL COMMENT '類別名稱',
  `sort_num` decimal(10,2) NOT NULL DEFAULT '1.00' COMMENT '排序序號',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='角色類別表';

role_desc表是角色描述信息表,其中包含了角色名稱,簡介,圖片等內(nèi)容,主要是用于角色列表展示的。
建表語句如下:

CREATE TABLE `role_desc` (
  `id` varchar(10) NOT NULL COMMENT '主鍵',
  `title` varchar(512) NOT NULL COMMENT '標題',
  `description` text COMMENT '內(nèi)容',
  `chat` text COMMENT '聊天內(nèi)容',
  `image` varchar(128) NOT NULL COMMENT '圖片',
  `role_id` int DEFAULT NULL COMMENT 'roleId',
  `sort_num` decimal(10,2) NOT NULL DEFAULT '1.00' COMMENT '排序序號',
  `post_status` smallint DEFAULT '0' COMMENT '上線狀態(tài)',
  `create_date` datetime DEFAULT NULL COMMENT '創(chuàng)建時間',
  `update_date` datetime DEFAULT NULL COMMENT '更新時間',
  `role_type_id` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `type_index` (`role_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='角色描述表';

福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源,chatgpt,chatgpt,小程序,開源

role表,是角色參數(shù)表,用于保存角色的prompt和調(diào)用openAI的一些核心參數(shù),如模型,最大token等
建表語句如下:

CREATE TABLE `role` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '唯一標識,自動遞增',
  `role_name` varchar(255) DEFAULT NULL,
  `role_message` text,
  `model` varchar(255) NOT NULL DEFAULT 'gpt-3.5-turbo',
  `create_time` datetime NOT NULL,
  `temperature` double NOT NULL DEFAULT '0.2',
  `max_tokens` int NOT NULL DEFAULT '2048',
  `top_p` double NOT NULL DEFAULT '1',
  `presence_penalty` double NOT NULL DEFAULT '0',
  `frequency_penalty` double NOT NULL DEFAULT '0',
  `n` int NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb3;

福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源,chatgpt,chatgpt,小程序,開源

總結(jié)

本次分享,只分享了后端代碼,前端和小程序端,下次繼續(xù)分享。如果你想繼續(xù)了解的話,可以關(guān)注我的公眾號【程序員修煉】。

最后,代碼獲取方式,關(guān)注公眾號,發(fā)送"ChatGPTService"獲取后端代碼,發(fā)送"ChatGPTWeChat"獲取小程序代碼,發(fā)送"ChatGPTWeb"獲取前端代碼。

另外,有任何問題,可加我微信【cxyxl66】進行咨詢,來者不拒。文章來源地址http://www.zghlxwxcb.cn/news/detail-706960.html

到了這里,關(guān)于福利!打造自己的ChatGPT聊天小程序,前后端代碼全開源的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包