之前的章节算是已经比较完整的实现了聊天功能,本来打算直接结束的。前几天听说文心一言4.0开放了公测,所以也去申请了一下,2天后就收到了通过短信。通过以后,可以在之前申请的应用列表中,点击“详情”,在“服务配置”的最后一行可以看到ERNIE-Bot 4.0
目前一直到10月底,4.0接口是免费的,大家抓紧时间体验。
我们看一下API文档,发现调用方式和之前的类似,我们可以调整一下代码底层,将其配置化,以方便我们在不同的模型间进行切换。
config/config.default.js调整代码如下:
config.ernie = {
client_id: '填入您的API Key', //API Key
client_secret: '填入您的Secret Key',//Secret Key
access_token: '', //先置空,后续由程序填充
expire_day: 30, //access_token过期时长(天)
gpt_model: 'ERNIE-Bot-4', //此处值对应gpt_list中的type
gpt_list: [{
type: 'ERNIE-Bot-4', //文心一言4.0
url: 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro'
}, {
type: 'ERNIE-Bot', //文心一言
url: 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions'
}, {
type: 'ERNIE-Bot-turbo', //文心一言轻量版
url: 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant'
}]
}
app/service/ernie.js全部代码如下:
const {
Service
} = require('egg');
const moment = require('moment');
class ErnieService extends Service {
async getAccessToken() {
console.log('===================ErnieService getAccessToken=====================');
let ctx = this.ctx;
try {
const res = await ctx.curl(
`https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${ctx.app.config.ernie.client_id}&client_secret=${ctx.app.config.ernie.client_secret}`, {
method: 'GET',
rejectUnauthorized: false,
data: {},
headers: {},
timeout: 30000,
contentType: 'json',
dataType: 'json',
})
console.log(res)
if (res.data.access_token) {
console.log('access_token', ctx.app.config.ernie.access_token)
return res.data.access_token;
}
} catch (error) {
console.log(error)
}
return null;
}
async sendMsg(msg) {
console.log('===================ErnieService sendMsg=====================');
console.log(JSON.stringify(msg));
let ctx = this.ctx;
let gpt_url;
for (let i of ctx.app.config.ernie.gpt_list) {
if (i.type === ctx.app.config.ernie.gpt_model) {
gpt_url = i.url;
break;
}
}
if (!gpt_url) {
console.log('您设置的gpt_model值不存在');
return null;
}
try {
const res = await ctx.curl(
`${gpt_url}?access_token=${ctx.app.config.ernie.access_token}`, {
method: 'POST',
rejectUnauthorized: false,
data: {
"messages": msg
},
timeout: 30000,
contentType: 'json',
dataType: 'json',
})
console.log(res)
if (res.data) {
if (res.data.error_code == '111') { //token过期
await ctx.service.ernie.checkAccessToken(true);
}
return res.data;
}
return null;
} catch (error) {
console.log(error)
return null;
}
}
async checkAccessToken(forceReflesh) { //forceReflesh强制刷新
console.log('===================ErnieService checkAccessToken=====================');
let ctx = this.ctx;
const query = {};
const accessToken = await ctx.model.AccessToken.findOne(query);
if (accessToken) {
console.log('accessToken', accessToken.access_token, accessToken.updated_at);
if (moment(new Date()).diff(moment(accessToken.updated_at), 'days') >= ctx.app.config.ernie.expire_day -
1 || forceReflesh) { //提前一天刷新
console.log('accessToken已失效,重新获取中')
const accessTokenStr = await ctx.service.ernie.getAccessToken();
if (accessTokenStr) {
await accessToken.update({
accessToken: accessTokenStr,
updated_at: moment().format('YYYY-MM-DD HH:mm:ss')
});
ctx.app.config.ernie.access_token = accessTokenStr;
console.log('accessToken更新成功');
} else {
console.log('accessToken获取失败');
}
} else {
ctx.app.config.ernie.access_token = accessToken.access_token;
console.log('accessToken在有效期内');
}
} else {
console.log('accessToken不存在');
const accessTokenStr = await ctx.service.ernie.getAccessToken();
if (accessTokenStr) {
const queryData = await ctx.model.AccessToken.create({
access_token: accessTokenStr
});
ctx.app.config.ernie.access_token = accessTokenStr;
console.log('accessToken更新成功');
} else {
console.log('accessToken获取失败');
}
}
}
}
module.exports = ErnieService;
最近发现access_token有时候莫名其妙的就过期,所以我们加入了强制刷新的逻辑。我们在app.js中也可以加入强制刷新,让服务一启动就刷新access_token。
app.js部分代码:
app.ready(async () => {
console.log("==app ready==");
let ctx = app.createAnonymousContext();
await ctx.service.ernie.checkAccessToken(true); //强制刷新AccessToken
await ctx.service.wechat.startBot(); //初始化BOT
})
至此,我们已经可以在三种不同的模型直接快速切换,仅需要调整config.ernie.gpt_model配置项。
本章完整代码在这里下载。运行前请先申请文心一言4.0测试资格,配置好config/config.default.js里面config.ernie下的client_id和client_secret配置项。