????????上一章介紹了eggjs+wechaty搭建一個簡單的微信聊天機器人,只是實現(xiàn)了簡單的回復(fù),這一章我們將對接ERNIE-Bot接口,實現(xiàn)智能回復(fù)。
access_token的請求
config.default.js配置
????????我們在上一章代碼基礎(chǔ)上進行調(diào)整,首先我們要加入access_token的請求邏輯。第一章我們說過,請求需要使用應(yīng)用對應(yīng)的API Key,Secret Key作為入?yún)?。eggjs規(guī)定了配置的寫法,我們可以將其配置在config/config.default.js里面。
//配置ernie
config.ernie = {
client_id: '填入您的API Key', //API Key
client_secret: '填入您的Secret Key',//Secret Key
access_token: '',//先置空,后續(xù)由程序填充
expire_day: 30 //access_token過期時長(天)
}
ernie.js定義getAccessToken
????????我們在app/service目錄增加ernie.js。
????????ernie.js文件專門用來和ERNIE-Bot接口進行交互,代碼如下:
const {
Service
} = require('egg');
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) {
ctx.app.config.ernie.access_token = res.data.access_token;
console.log('access_token', ctx.app.config.ernie.access_token)
}
} catch (error) {
console.log(error)
}
}
}
module.exports = ErnieService;
我們按eggjs的service的寫法,定義了一個方法,用來請求access_token,但是這樣寫并不能執(zhí)行,我們需要有個邏輯,在應(yīng)用啟動完畢后會調(diào)用這個方法。
app.js執(zhí)行g(shù)etAccessToken
????????我們在根目錄增加app.js。
app.js代碼如下:
module.exports = app => {
app.beforeStart(async () => {
// 應(yīng)用會等待這個函數(shù)執(zhí)行完成才啟動
console.log("==app beforeStart==");
});
app.ready(async () => {
console.log("==app ready==");
let ctx = app.createAnonymousContext();
ctx.service.ernie.getAccessToken(); //請求AccessToken
})
app.beforeClose(async () => {
console.log("==app beforeClose==");
})
};
我們執(zhí)行命令npm run dev啟動項目,看到最終會打印出access_token,有了access_token我們繼續(xù)開發(fā)接口請求函數(shù)sendMsg。
對話請求
ernie.js定義sendMsg
sendMsg函數(shù)用于調(diào)用ERNIE-Bot會話接口,傳入對話內(nèi)容并返回對話結(jié)果。在class ErnieService中加入以下代碼:
async sendMsg(msg) {
console.log('===================ErnieService sendMsg=====================');
let ctx = this.ctx;
try {
const res = await ctx.curl(
`https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?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) {
return res.data;
}
return null;
} catch (error) {
console.log(error)
return null;
}
}
wechat.js
我們在wechat.js中,將原先的邏輯調(diào)整一下,主要是改兩個地方,
1、我們在之前的代碼中經(jīng)常有看到ctx這個變量,可以通過他獲取配置文件的參數(shù)值。但Service文件中的ctx的獲取只能通過app.js調(diào)用Service中函數(shù)的方式來獲得。所以我們將機器人初始化的操作定義在startBot()方法中,由app.js來執(zhí)行這個方法,就可以接收到ctx的值。
2、原先回復(fù)是直接扔回用戶發(fā)的信息的,現(xiàn)在將其對接到ernie.js中的sendMsg方法。
wechat.js全部代碼如下:
const {
Service
} = require('egg');
const {
WechatyBuilder,
ScanStatus
} = require("wechaty");
const qrcode = require("qrcode-terminal");
let ctx;
let wechaty;
let startStatus = false;
const onMessage = async (message) => {
console.log(`收到消息: ${message}`);
if (message.type() === wechaty.Message.Type.Text) {
const userMsg = await message.text();
try {
let msgRecord = [{
"role": "user",
"content": userMsg
}];
let res = await ctx.service.ernie.sendMsg(msgRecord);
if (res) {
if (res.error_code) {
message.say(JSON.stringify(res));
console.log(`報錯: ${JSON.stringify(res)}`);
} else {
if (res.result) {
message.say(res.result);
console.log(`回復(fù): ${res.result}`);
}
}
}
} catch (error) {
console.log(error);
message.say(JSON.stringify(error));
}
}
};
const onLogout = (user) => {
console.log(`用戶 ${user} 退出成功`);
};
const onLogin = async (user) => {
console.log(`用戶 ${user} 登錄成功`);
};
const onError = console.error;
const onScan = (code, status) => {
// status: 2代表鏈接等待調(diào)用,3代表鏈接已打開,這個鏈接實際上是提供一個登錄的二維碼供掃描
if (status === ScanStatus.Waiting) {
// status: 2代表等待,3代表掃碼完成
qrcode.generate(code, {
small: true
}, console.log)
}
};
class WechatService extends Service {
async startBot() {
console.log('===================WechatService startBot=====================');
ctx = this.ctx;
if (startStatus && wechaty) {
if (wechaty.isLoggedIn) {
await wechaty.logout();
}
await wechaty.stop();
startStatus = false;
wechaty = null;
}
wechaty = await WechatyBuilder.build();
wechaty
.on("scan", onScan)
.on("login", onLogin)
.on("logout", onLogout)
.on("error", onError)
.on("message", onMessage);
await wechaty.start();
startStatus = true;
}
}
module.exports = WechatService;
app.js執(zhí)行startBot
在AccessToken請求后加入初始化BOT
app.ready(async () => {
console.log("==app ready==");
let ctx = app.createAnonymousContext();
await ctx.service.ernie.getAccessToken(); //請求AccessToken
await ctx.service.wechat.startBot(); //初始化BOT
})
至此,我們已經(jīng)實現(xiàn)了一次會話的功能。多輪對話的功能等下一章再詳述。文章來源:http://www.zghlxwxcb.cn/news/detail-771406.html
本章完整代碼在這里???????下載。運行前請配置好config/config.default.js里面config.ernie下的client_id和client_secret配置項。文章來源地址http://www.zghlxwxcb.cn/news/detail-771406.html
到了這里,關(guān)于手把手教你搭建微信聊天機器人系列(三):搭建對接文心一言(ERNIE-Bot大模型)接口的微信聊天機器人的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!