GPT-3.5&速搭微信小程序
前言
想必大家都收到OpenAI开放了ChatGPT API的消息,之前的API也尝试过接入过个人微信号,给好基友们体验体验,但是效果不太好,已经被他们干废一个小号。
公众号又有三秒断连的机制,也就没写下去了,这次整个小程序。
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)
})
返回结果如下:
我们成功与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 ...
// ...
一个简单的接口就这样完成了。
关于其他参数的应用
目前我们只使用了model和messages参数,其中messages还可以选择性的去除对话中的信息,ChatGPT API是每次都要传输完整的上下文消息的,所以我们还可以与前端联动,选择删除一些无用的信息,保留有用的信息,提高回答的准确性。
n:一次性返回多个不同值,可以避免多次重复询问
logit_bias:调整特定词汇在结果中出现的可能性,可以实现减少重复和屏蔽特定词汇的功能
temperature/top_p:调整结果的相关性和准确性,可以在需要发散思维时使用,官方建议二者调整其中一个,不建议二者都调整。
这些参数也可以在前端通过发送指令的方式进行调整。
微信小程序
对话界面
我们基于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,但是今天是周五欸,下机。
代码先丢上去了
小程序代码
来源:juejin.cn/post/7206292770276163640