欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用chatgpt實(shí)現(xiàn)微信聊天小程序的代碼示例

 更新時(shí)間:2023年05月21日 15:49:54   作者:禿頭披風(fēng)俠.  
這篇文章主要介紹了使用chatgpt實(shí)現(xiàn)微信聊天小程序(秒回復(fù)),文中有詳細(xì)的代碼示例,對(duì)大家了解chatgpt聊天有一定的幫助,感興趣的同學(xué)可以參考閱讀

前言

前一段時(shí)間使用java來(lái)調(diào)用chatgpt的接口,然后寫了一個(gè)簡(jiǎn)單小程序,java調(diào)用chatgpt接口,實(shí)現(xiàn)專屬于自己的人工智能助手,事實(shí)上,這個(gè)程序毛病挺多的,最不能讓人接受的一點(diǎn)就是返回速度非常緩慢(即使使用非常好的外網(wǎng)服務(wù)器)。

現(xiàn)在,我改進(jìn)了一下程序,使用異步請(qǐng)求的方式,基本可以實(shí)現(xiàn)秒回復(fù)。并且還基于webSocket編寫了一個(gè)微信小程序來(lái)進(jìn)行交互,可以直接使用微信小程序來(lái)進(jìn)行體驗(yàn)。

效果展示

部分截圖如下

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

原理說(shuō)明

java調(diào)用chatgpt接口,實(shí)現(xiàn)專屬于自己的人工智能助手 我說(shuō)明了java調(diào)用chatgpt的基本原理,這里的代碼就是對(duì)這個(gè)代碼的改進(jìn),使用異步請(qǐng)求的方式來(lái)進(jìn)行。

在這里插入圖片描述

注意看官方文檔,我們?cè)谡?qǐng)求時(shí)可以提供一個(gè)參數(shù)stream,然后就可以實(shí)現(xiàn)按照流的形式進(jìn)行返回,這種方式基本可以做到?jīng)]有延遲就給出答案。

由于這次改進(jìn)的思路主要就是將請(qǐng)求改為了異步,其他的基本一樣,所以就不做解釋,直接給出代碼了,代碼上面都有注釋

    /**
     * 這個(gè)方法用于測(cè)試的,可以在控制臺(tái)打印輸出結(jié)果
     *
     * @param chatGptRequestParameter 請(qǐng)求的參數(shù)
     * @param question                問(wèn)題
     */
    public void printAnswer(ChatRequestParameter chatGptRequestParameter, String question) {
        asyncClient.start();
        // 創(chuàng)建一個(gè)post請(qǐng)求
        AsyncRequestBuilder asyncRequest = AsyncRequestBuilder.post(url);

        // 設(shè)置請(qǐng)求參數(shù)
        chatGptRequestParameter.addMessages(new ChatMessage("user", question));

        // 請(qǐng)求的參數(shù)轉(zhuǎn)換為字符串
        String valueAsString = null;
        try {
            valueAsString = objectMapper.writeValueAsString(chatGptRequestParameter);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        // 設(shè)置編碼和請(qǐng)求參數(shù)
        ContentType contentType = ContentType.create("text/plain", charset);
        asyncRequest.setEntity(valueAsString, contentType);
        asyncRequest.setCharset(charset);

        // 設(shè)置請(qǐng)求頭
        asyncRequest.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
        // 設(shè)置登錄憑證
        asyncRequest.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey);

        // 下面就是生產(chǎn)者消費(fèi)者模型
        CountDownLatch latch = new CountDownLatch(1);
        // 用于記錄返回的答案
        StringBuilder sb = new StringBuilder();
        // 消費(fèi)者
        AbstractCharResponseConsumer<HttpResponse> consumer = new AbstractCharResponseConsumer<HttpResponse>() {
            HttpResponse response;

            @Override
            protected void start(HttpResponse response, ContentType contentType) throws HttpException, IOException {
                setCharset(charset);
                this.response = response;
            }

            @Override
            protected int capacityIncrement() {
                return Integer.MAX_VALUE;
            }

            @Override
            protected void data(CharBuffer src, boolean endOfStream) throws IOException {
                // 收到一個(gè)請(qǐng)求就進(jìn)行處理
                String ss = src.toString();
                // 通過(guò)data:進(jìn)行分割,如果不進(jìn)行此步,可能返回的答案會(huì)少一些內(nèi)容
                for (String s : ss.split("data:")) {
                    // 去除掉data:
                    if (s.startsWith("data:")) {
                        s = s.substring(5);
                    }
                    // 返回的數(shù)據(jù)可能是(DONE)
                    if (s.length() > 8) {
                        // 轉(zhuǎn)換為對(duì)象
                        ChatResponseParameter responseParameter = objectMapper.readValue(s, ChatResponseParameter.class);
                        // 處理結(jié)果
                        for (Choice choice : responseParameter.getChoices()) {
                            String content = choice.getDelta().getContent();
                            if (content != null && !"".equals(content)) {
                                // 保存結(jié)果
                                sb.append(content);
                                // 將結(jié)果使用webSocket傳送過(guò)去
                                System.out.print(content);
                            }
                        }
                    }
                }
            }

            @Override
            protected HttpResponse buildResult() throws IOException {
                return response;
            }

            @Override
            public void releaseResources() {
            }
        };

        // 執(zhí)行請(qǐng)求
        asyncClient.execute(asyncRequest.build(), consumer, new FutureCallback<HttpResponse>() {

            @Override
            public void completed(HttpResponse response) {
                latch.countDown();
                chatGptRequestParameter.addMessages(new ChatMessage("assistant", sb.toString()));
                System.out.println("回答結(jié)束?。?!");
            }

            @Override
            public void failed(Exception ex) {
                latch.countDown();
                System.out.println("failed");
                ex.printStackTrace();
            }

            @Override
            public void cancelled() {
                latch.countDown();
                System.out.println("cancelled");
            }

        });
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

大家代碼可以直接不看,反正最終的效果就是可以實(shí)現(xiàn)問(wèn)了問(wèn)題就返回結(jié)果。運(yùn)行效果如下

在這里插入圖片描述

在這里插入圖片描述

可以發(fā)現(xiàn),輸出就類似于官方的那種效果,一個(gè)字一個(gè)字的輸出

服務(wù)器端代碼說(shuō)明

我使用java搭建了一個(gè)簡(jiǎn)單的服務(wù)器端程序,提供最基礎(chǔ)的用戶登錄校驗(yàn)功能,以及提供了WebSocket通信。

用戶校驗(yàn)的代碼

package com.ttpfx.controller;

import com.ttpfx.entity.User;
import com.ttpfx.service.UserService;
import com.ttpfx.utils.R;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ttpfx
 * @date 2023/3/29
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    public static ConcurrentHashMap<String, User> loginUser = new ConcurrentHashMap<>();

    public static ConcurrentHashMap<String, Long> loginUserKey = new ConcurrentHashMap<>();
    @RequestMapping("/login")
    public R login(String username, String password) {
        if (username == null) return R.fail("必須填寫用戶名");


        User user = userService.queryByName(username);
        if (user == null) return R.fail("用戶名不存在");
        String targetPassword = user.getPassword();
        if (targetPassword == null) return R.fail("用戶密碼異常");
        if (!targetPassword.equals(password)) return R.fail("密碼錯(cuò)誤");

        loginUser.put(username, user);
        loginUserKey.put(username, System.currentTimeMillis());
        return R.ok(String.valueOf(loginUserKey.get(username)));
    }

    @RequestMapping("/logout")
    public R logout(String username) {
        loginUser.remove(username);
        loginUserKey.remove(username);
        return R.ok();
    }

    @RequestMapping("/checkUserKey")
    public R checkUserKey(String username, Long key){
        if (username==null || key == null)return R.fail("用戶校驗(yàn)異常");
        if (!Objects.equals(loginUserKey.get(username), key)){
            return R.fail("用戶在其他地方登錄?。?!");
        }
        return R.ok();
    }

    @RequestMapping("/loginUser")
    public R loginUser(){
        return R.ok("success",loginUser.keySet());
    }
}

基于webSocket通信的代碼

package com.ttpfx.server;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ttpfx.entity.UserLog;
import com.ttpfx.model.ChatModel;
import com.ttpfx.service.UserLogService;
import com.ttpfx.service.UserService;
import com.ttpfx.vo.chat.ChatRequestParameter;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ttpfx
 * @date 2023/3/28
 */
@Component
@ServerEndpoint("/chatWebSocket/{username}")
public class ChatWebSocketServer {

    /**
     * 靜態(tài)變量,用來(lái)記錄當(dāng)前在線連接數(shù)。應(yīng)該把它設(shè)計(jì)成線程安全的。
     */
    private static int onlineCount = 0;
    /**
     * concurrent包的線程安全Map,用來(lái)存放每個(gè)客戶端對(duì)應(yīng)的MyWebSocket對(duì)象。
     */
    private static ConcurrentHashMap<String, ChatWebSocketServer> chatWebSocketMap = new ConcurrentHashMap<>();

    /**
     * 與某個(gè)客戶端的連接會(huì)話,需要通過(guò)它來(lái)給客戶端發(fā)送數(shù)據(jù)
     */
    private Session session;
    /**
     * 接收的username
     */
    private String username = "";

    private UserLog userLog;

    private static UserService userService;
    private static UserLogService userLogService;

    @Resource
    public void setUserService(UserService userService) {
        ChatWebSocketServer.userService = userService;
    }

    @Resource
    public void setUserLogService(UserLogService userLogService) {
        ChatWebSocketServer.userLogService = userLogService;
    }

    private ObjectMapper objectMapper = new ObjectMapper();
    private static ChatModel chatModel;

    @Resource
    public void setChatModel(ChatModel chatModel) {
        ChatWebSocketServer.chatModel = chatModel;
    }

    ChatRequestParameter chatRequestParameter = new ChatRequestParameter();

    /**
     * 建立連接
     * @param session 會(huì)話
     * @param username 連接用戶名稱
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        this.session = session;
        this.username = username;
        this.userLog = new UserLog();
        // 這里的用戶id不可能為null,出現(xiàn)null,那么就是非法請(qǐng)求
        try {
            this.userLog.setUserId(userService.queryByName(username).getId());
        } catch (Exception e) {
            e.printStackTrace();
            try {
                session.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        this.userLog.setUsername(username);
        chatWebSocketMap.put(username, this);
        onlineCount++;
        System.out.println(username + "--open");
    }

    @OnClose
    public void onClose() {
        chatWebSocketMap.remove(username);
        System.out.println(username + "--close");
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println(username + "--" + message);
        // 記錄日志
        this.userLog.setDateTime(LocalDateTime.now());
        this.userLog.setPreLogId(this.userLog.getLogId() == null ? -1 : this.userLog.getLogId());
        this.userLog.setLogId(null);
        this.userLog.setQuestion(message);
        long start = System.currentTimeMillis();
        // 這里就會(huì)返回結(jié)果
        String answer = chatModel.getAnswer(session, chatRequestParameter, message);
        long end = System.currentTimeMillis();
        this.userLog.setConsumeTime(end - start);
        this.userLog.setAnswer(answer);
        userLogService.save(userLog);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    public static void sendInfo(String message, String toUserId) throws IOException {
        chatWebSocketMap.get(toUserId).sendMessage(message);
    }
}

我們只需要編寫簡(jiǎn)單的前端代碼,就可以實(shí)現(xiàn)和后端的socket通信。對(duì)于后端,我們只需要改一下apiKey和數(shù)據(jù)庫(kù)配置就可以直接運(yùn)行了。

微信小程序代碼說(shuō)明

我寫了一個(gè)簡(jiǎn)單微信小程序來(lái)和后端進(jìn)行通信,界面如下

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述

大家只需要下載源代碼,然將程序中的ip改為自己服務(wù)器的ip即可

代碼鏈接

github的地址為 https://github.com/c-ttpfx/chatgpt-java-wx
可以直接使用 git clone https://github.com/c-ttpfx/chatgpt-java-wx.git 下載代碼到本地

我在github里面說(shuō)明了安裝使用的基本步驟,大家按照步驟使用即可

總結(jié)

上面聊天小程序就是我花2天寫出來(lái)的,可能會(huì)有一些bug,我自己測(cè)試的時(shí)候倒是沒(méi)有怎么遇到bug,聊天和登錄功能都能正常使用。

對(duì)于微信小程序,由于我不是專業(yè)搞前端的,就只東拼西湊實(shí)現(xiàn)了最基本的功能(登錄、聊天),大家可以自己寫一個(gè),反正后端接口都提供好了嘛,也不是很難,不想寫也可以將就使用我的。

更新日志

對(duì)代碼進(jìn)行了重構(gòu),最新的代碼已經(jīng)支持代理,通過(guò)在application.yaml里面進(jìn)行簡(jiǎn)單配置即可使用

gpt:
  proxy:
    host: 127.0.0.1
    port: 7890

以上就是使用chatgpt實(shí)現(xiàn)微信聊天小程序的代碼示例的詳細(xì)內(nèi)容,更多關(guān)于chatgpt微信聊天小程序的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java 讀寫Properties配置文件詳解

    Java 讀寫Properties配置文件詳解

    這篇文章主要介紹了Java 讀寫Properties配置文件詳解的相關(guān)資料,這里舉例說(shuō)明該如何實(shí)現(xiàn),具有參考價(jià)值,需要的朋友可以參考下
    2016-11-11
  • Java之Spring認(rèn)證使用Profile配置運(yùn)行環(huán)境講解

    Java之Spring認(rèn)證使用Profile配置運(yùn)行環(huán)境講解

    這篇文章主要介紹了Java之Spring認(rèn)證使用Profile配置運(yùn)行環(huán)境講解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Mybatis-Plus?CRUD操作方法

    Mybatis-Plus?CRUD操作方法

    通用?Service?CRUD?封裝?IService?接口,進(jìn)一步封裝?CRUD?采用?get?查詢、remove?刪除?、list?查詢集合、page?分頁(yè)的前綴命名方式區(qū)分?Mapper?層避免混淆,這篇文章主要介紹了Mybatis-Plus?CRUD的相關(guān)知識(shí),需要的朋友可以參考下
    2023-10-10
  • Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡(jiǎn)單實(shí)例

    Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡(jiǎn)單實(shí)例

    下面小編就為大家?guī)?lái)一篇Java實(shí)現(xiàn)監(jiān)控多個(gè)線程狀態(tài)的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • SpringMVC統(tǒng)一異常處理實(shí)例代碼

    SpringMVC統(tǒng)一異常處理實(shí)例代碼

    這篇文章主要介紹了SpringMVC統(tǒng)一異常處理實(shí)例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • MyBatis多表查詢和注解開(kāi)發(fā)案例詳解

    MyBatis多表查詢和注解開(kāi)發(fā)案例詳解

    這篇文章主要介紹了MyBatis多表查詢和注解開(kāi)發(fā),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • SpringMVC數(shù)據(jù)頁(yè)響應(yīng)ModelAndView實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)

    SpringMVC數(shù)據(jù)頁(yè)響應(yīng)ModelAndView實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)

    本文主要介紹了SpringMVC數(shù)據(jù)頁(yè)響應(yīng)ModelAndView實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • 詳解spring boot mybatis全注解化

    詳解spring boot mybatis全注解化

    這篇文章主要介紹了spring boot mybatis全注解化的相關(guān)資料,需要的朋友可以參考下
    2017-09-09
  • Java中對(duì)象的創(chuàng)建和銷毀過(guò)程詳析

    Java中對(duì)象的創(chuàng)建和銷毀過(guò)程詳析

    這篇文章主要介紹了Java中對(duì)象的創(chuàng)建和銷毀過(guò)程,對(duì)象的創(chuàng)建過(guò)程包括類加載檢查、內(nèi)存分配、初始化零值內(nèi)存、設(shè)置對(duì)象頭和執(zhí)行init方法,對(duì)象的銷毀過(guò)程由垃圾回收機(jī)制負(fù)責(zé),文中介紹的非常詳細(xì),需要的朋友可以參考下
    2025-02-02
  • 微信公眾號(hào)開(kāi)發(fā)之設(shè)置自定義菜單實(shí)例代碼【java版】

    微信公眾號(hào)開(kāi)發(fā)之設(shè)置自定義菜單實(shí)例代碼【java版】

    這篇文章主要介紹了微信公眾號(hào)開(kāi)發(fā)之設(shè)置自定義菜單實(shí)例代碼,本實(shí)例是為了實(shí)現(xiàn)在管理后臺(tái)實(shí)現(xiàn)微信菜單的添加刪除管理。需要的朋友可以參考下
    2018-06-06

最新評(píng)論