您现在的位置是:首页 >技术教程 >对接ChatGPT开发对话机器人小程序网站首页技术教程

对接ChatGPT开发对话机器人小程序

墨家巨子@俏如来 2023-07-07 00:00:03
简介对接ChatGPT开发对话机器人小程序

前言

ChatGPT已经非常火爆了,企业开始招聘ChatGPT工程师,可能对接ChatGPT接口进行企业级开发是程序员必备的技能了。本篇文章主要是基于ChatGPT开发接口进行对接,使用微信小程序制作一款自己的聊天机器人,通过这一案例你可以展开无限的扩展

整体设计

整体设计比较简单,我们使用微信小程序作为客户端界面提供用户使用,小程序和后台使用WebSocket进行通信。
在这里插入图片描述
最终效果如下
在这里插入图片描述

ChatGPT接口对接

注意要有梯子才可以访问,接口参考文档:https://platform.openai.com/docs/api-reference/chat ,在Api Reference 接口文档中找到Chat ,里面有Chat对话接口的请求说明

在这里插入图片描述
根据文档说明,我们需要构建一个请求地址为:https://api.openai.com:443/v1/chat/completions ,post请求提交,参数为:

{
    "model":"gpt-3.5-turbo",
    "messages":[
        {
            "role":"user",
            "content":"SpringBoot是什么"
        }
    ]
}

这样还不够,如果直接访问会报错:apikey不存在,我们还需要创建一个APIKEY,地址:https://platform.openai.com/account/api-keys

在这里插入图片描述

然后我这里使用Postmain做一个简单测试,请求头加上APIKEY
在这里插入图片描述
在Body中构建请求参数效果如下
在这里插入图片描述
根据结果可以看到返回的格式为

{
    "id": "chatcmpl-7A6KvI2ybOjR2xHvejz3ysoDFmA54",
    "object": "chat.completion",
    "created": 1682641993,
    "model": "gpt-3.5-turbo-0301",
    "usage": {
        "prompt_tokens": 14,
        "completion_tokens": 147,
        "total_tokens": 161
    },
    "choices": [
        {
            "message": {
                "role": "assistant",
                "content": "Spring Boot 是 Spring 框架的一部分,是一个快速开发框架,可以从头开始构建独立的 Spring 应用程序。它通过自动配置功能和嵌入式 Web 服务器可以快速地开发出一个基于 Spring 框架的 Web 应用程序。Spring Boot 构建于 Spring 框架之上,使得开发者可以更方便地集成 Spring 框架的各种组件和其他第三方库,同时避免了繁琐的 XML 配置。"
            },
            "finish_reason": "stop",
            "index": 0
        }
    ]
}

编写后台

后台我们使用SpringBoot快速开发,主要是整合websocket收发消息,需要导入的pom如下

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

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>



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


        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>
        
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

第二步,启动类中定义RestTemplate,方便后续向ChatGPT发请求

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


    @Bean
    public RestTemplate restTemplate(){
        
        return new RestTemplate();
    }

}

第三步,配置websocket,如下

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

第四步:编写请求实体类,根据ChatGPT要求的请求参数来封装

@Data
public class ChatMessageParam {
    //model 代表了使用chatgpt的哪个模型
    private String model = "gpt-3.5-turbo";
    //请求消息,要去以数组格式
    private List<ChatMessage> messages = new ArrayList<>();
    //往message中添加message
    public void addMessages(ChatMessage message) {
        this.messages.add(message);
    }

    public ChatMessageParam(){}

    public ChatMessageParam(ChatMessage message){
        this.messages.add(message);
    }
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ChatMessage {
    private String role;
    private String content;
}

下面是参数配置application.yaml中的配置和属性对象

server:
  port: 80
chatgpt:
  apikey: 你的apikey
  apiurl: "https://api.openai.com:443/v1/chat/completions"


//参数对象
@Component
@ConfigurationProperties(prefix = "chatgpt")
@Data
public class ChatGptProperties {
    private String apikey;
    private String apiurl;
}


第五步:编写请求发送逻辑,底层使用的是RestTmpalte来发送.这里需要两个参数 APIKEY和URL地址,我在yaml中进行了配置,并使用对象进行绑定


@Component
@Slf4j
public class ChatHttpSender {
	//HTTP客户端
    @Autowired
    private RestTemplate restTemplate;

    //ChtGPT配置
    @Autowired
    private ChatGptProperties chatProperties;

    public String post(String message){
        //封装参数对象
        ChatMessageParam param = new ChatMessageParam(new ChatMessage(ChatGptConstants.ROLE,message));
        //添加请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        //设置apikey
        httpHeaders.add(AUTHORIZATION,String.format(PRE_BEARER,chatProperties.getApikey()));
        httpHeaders.add("text/plain", StandardCharsets.UTF_8.toString());
        httpHeaders.add("Content-Type", "application/json");
        //构建Post请求
        HttpEntity entity = new HttpEntity(param,httpHeaders);
        log.info("发送请求 {}",entity);
        //向ChatGPT发送请求
        String json = restTemplate.postForObject(chatProperties.getApiurl(), entity, String.class);
        //解析结果,拿到message
        JSONArray choices = JSON.parseObject(json).getJSONArray("choices");
        JSONObject jsonObject = choices.getJSONObject(0);
        String content = jsonObject.getJSONObject("message").getString("content");
        log.info("拿到结果 {}",content);
        return content;
    }
}

//常量类
public class ChatGptConstants {

    public static final String MODEL = "gpt-3.5-turbo";
    public static final String ROLE = "user";

    public static final String AUTHORIZATION = "Authorization";
    public static final String PRE_BEARER  = "Bearer %s";
}

第六步,编写websocket服务端,主需要是收到消息后调用ChatHttpSender发送请求,然后把结果写回给客户端。这里我使用的是RedsTemplate调用ChatGpt接口,因为是同步,会出现等待的情况

package org.example.socket;

import lombok.extern.slf4j.Slf4j;
import org.example.http.ChatHttpSender;
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.util.concurrent.ConcurrentHashMap;


@Component
//服务器端点
@ServerEndpoint("/chatWebSocket/{uid}")
@Slf4j
public class ChatSocketServer {
    //定义了一个请求发送器
    private static ChatHttpSender httpSender;

    //用map把websocket客户端存储七年,客户端集合,key是uid
    private static ConcurrentHashMap<String, ChatSocketServer> socketClients = new ConcurrentHashMap<>();

    //会话对象,通过他来向客户端发请求
    private Session session;

    //接收uid,代表客户端用户
    private String uid = "";

    //注入sender
    @Resource
    public void setHttpSender(ChatHttpSender httpSender){
        this.httpSender = httpSender;
    }

    /**
     * 建立连接
     * @param session 会话
     * @param uid 连接用户名称
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("uid") String uid) {
        this.session = session;
        this.uid = uid;
        socketClients.put(uid, this);
        log.info("客户端{} , 建立连接",uid);
    }

    @OnClose
    public void onClose() {
        socketClients.remove(uid);
        log.info("客户端{} , 关闭连接",uid);
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到消息,UID:{} 内容: {} ",uid,message);
        try {
            //httpSender向chatGPT发起请求,拿到结果
            String result = httpSender.post(message);
            //给客户端返回结果
            sendMessage(result);
        }catch (Exception e){
            e.printStackTrace();
            sendMessage("服务器故障");
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
        log.error("发生错误,{} ",uid,error.getMessage());
    }

    public void sendMessage(String message)  {
        log.error("发送消息,UID:{} ,内容:{} ",uid,message);
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

服务端上云

ChatGPT需要梯子才能访问,所以在本地是测不通的,建议直接买一台国外的服务器进行部署。购买云服务器可以看这篇文章《购买一台云服务器》,记得买国外的服务器。然后把项目打成jar包,进入项目根目录执行:mvn install ,在target目录找到项目比如:springboot-chatgpt-1.0-SNAPSHOT.jar 。然后上传到云服务器上,执行Java -jar 即可

在这里插入图片描述
到此服务器端搞定。

小程序端

微信小程序大家可以根据微信小程序官网教程去下载客户端工具,然后导入已有前端代码来测试。前端主要是布局和写websocket客户端,这里截一下核心代码

onShow: function () {
    //链接服务器端
    wx.connectSocket({
      url: 'ws://170.106.152.44/chatWebSocket/uid' + Math.round(Math.random()*10)
    })

    wx.onSocketOpen((res) => {
      socketOpen = true
      
      wx.showToast({
        icon: 'none',
        title: '会话建立成功',
        duration: 500
      })
      socketMsgQueue = []
      //处理返回的消息
      wx.onSocketMessage((result) => {
        result.data = result.data.replace(" ", "&nbsp;");
        curAnsCount++;
        if (curAnsCount % lineCount == 0) {
          wx.createSelectorQuery().select('#chatPage').boundingClientRect(function (rect) {
            // 使页面滚动到底部
            wx.pageScrollTo({
              scrollTop: rect.bottom
            })
          }).exec()
        }
        msgList[msgList.length - 1].content = result.data
        this.setData({
          msgList
        })
      })
    })
  },

所有代码我已经上传的Gitee,有兴趣可以去参考一下。地址:https://gitee.com/baidu11.com/chatgpt

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。