当前位置:AIGC资讯 > AIGC > 正文

手把手教你搭建微信聊天机器人系列(五):对接文心一言4.0

        之前的章节算是已经比较完整的实现了聊天功能,本来打算直接结束的。前几天听说文心一言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配置项。

更新时间 2023-12-15