GPT-3.5&速搭微信小程序

5,407 阅读3分钟

本文正在参加 ✍🏻 技术视角深入 ChatGPT 征文活动

前言

想必大家都收到OpenAI开放了ChatGPT API的消息,之前的API也尝试过接入过个人微信号,给好基友们体验体验,但是效果不太好,已经被他们干废一个小号。

image.png

公众号又有三秒断连的机制,也就没写下去了,这次整个小程序。

ChatGPT API

先来看看ChatGPT API中我觉得最大的一个亮点:

  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
        {"role": "user", "content": "Where was it played?"}
    ]
)

与之前不同的是,我们可以以数组的形式存储上下文消息,不用像之前那样,想要实现多轮对话就得把消息全拼在一起,同时还显式的定义了角色,role属性表示其所属的角色,其中system是定于接口的行为,在对话中可以先使用system进行格式化,比如【你是一个前端工程师】,而user和assistant则是表示用户输入消息以及模型输出消息。通过这些定义,可以使模型变得更加清晰明确。

了解完信息格式后,我们直接上代码跑一下

const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
  apiKey: "YOU APIKEY",
});
const openai = new OpenAIApi(configuration);
const chat = async (content) => {
  try {
    const {data: { choices },} = await openai.createChatCompletion({
      model: "gpt-3.5-turbo",
      messages: content,
    });
    return choices[0].message;
  } catch (error) {
    return error;
  }
};
let content = [{ role: "user", content: "你好" }];
chat(content).then((res)=>{
    console.log(res)
})

返回结果如下:

image.png 我们成功与ChatGPT进行了一次对话,不过在此之前,还需要接收前端发送过来的信息,所以我们在外面套一个express

express

const express = require("express");
const app = express();
app.use(express.json()); 

app.post("/chat", (req, res) => {
  let content =req.body.content;
  chat(content).then((data)=>{
    res.send(data);
  })
});
app.listen(8080, () => {
  console.log("Server is running");
});

//const { Configuration ...
//const configuration ...
// ...

image.png

一个简单的接口就这样完成了。

关于其他参数的应用

目前我们只使用了model和messages参数,其中messages还可以选择性的去除对话中的信息,ChatGPT API是每次都要传输完整的上下文消息的,所以我们还可以与前端联动,选择删除一些无用的信息,保留有用的信息,提高回答的准确性。

n:一次性返回多个不同值,可以避免多次重复询问

logit_bias:调整特定词汇在结果中出现的可能性,可以实现减少重复和屏蔽特定词汇的功能

temperature/top_p:调整结果的相关性和准确性,可以在需要发散思维时使用,官方建议二者调整其中一个,不建议二者都调整。

这些参数也可以在前端通过发送指令的方式进行调整。

微信小程序

image.png

对话界面

我们基于messages来渲染对话界面

 <view wx:for="{{messages}}" wx:key="index" style="margin: 40rpx 0">
    <view class="user" wx:if="{{item.role=='user'}}">
      <image class="avatar" src="../../image/NO.0004.png"></image>
      <text class="content" bindtap="copyText" data-text="{{item.content}}">{{
        item.content
      }}</text>
    </view>
    <view class="assistant" wx:if="{{item.role=='assistant'}}">
      <image class="avatar" src="../../image/logo.png"></image>
      <text class="content" bindtap="copyText" data-text="{{item.content}}">{{
        item.content
      }}</text>
    </view>
  </view>

通过flex-direction区分用户与ChatGPT

.user {
    display: flex;
    justify-content: space-evenly;
    flex-direction: row-reverse;
}
.assistant {
    display: flex;
    justify-content: space-evenly;
}

发送事件

send函数主要流程是,把用户输入的信息push到messages,同时在界面中渲染,然后向api发送请求,返回信息后再push到messages中,同时在界面中渲染。

 send: function (e) {
        if(!/^\s*$/.test(this.data.inputValue)){
            let message = {"role": "user", "content":this.data.inputValue}
            this.data.messages.push(message)
            this.setData({
                messages:this.data.messages,
                inputValue:''
            });
            wx.request({
                url: 'http://127.0.0.1:8080/chat',
                method: 'POST',
                data: {
                  content: this.data.messages,
                },
                header: {
                  'content-type': 'application/json'
                },
                success:(res)=>{
                    this.data.messages.push(res.data.message)
                    this.setData({
                        messages:this.data.messages
                    });
                }
              })
        }else{
            wx.showToast({
                title: '输入不可为空',
                duration: 500,
                icon: 'none'
            }); 
        }

结尾

3月2号下午我写node的时候还能用,今天晚上写小程序时发现寄了,api应该是给墙了(一时间竟不知道哪边动的手),需要梯子。

关于send函数这里再细锁细琐,上面的传输方式随着聊天越聊越长,原方案是想发送给express做存储,前端每次只需要发送一条message,同时也能做聊天记录的保存,不过这不像在云开发中可以很方便的获取用户的openid,虽然可以用wx.login,但是今天是周五欸,下机。

代码先丢上去了 小程序代码

image.png