最近很火的ChatGPT
可以說已經滿大街可見了,到處都有各種各樣的體驗地址,有收費的也有免費的,總之是五花八門、花裏胡哨。
所以呢,最近我就在研究怎麼才能方便快捷的體驗到ChatGPT
的強大功能,其中一個就是:把ChatGPT
接入公衆號。畢竟公衆號是一種非常流行的社交媒體平臺,可以用來提供服務、推廣產品等。經過我的一番折騰,最後終於成功通過 Laf 實現了這個需求。
本文將詳細介紹如何使用 Laf 雲平臺將 ChatGPT 接入微信公衆號,實現智能問答、聊天機器人等功能。
1. 準備工作
首先需要註冊一個 Laf 平臺賬號:https://laf.run
註冊登錄之後,點擊新建,建立一個應用:
點擊開發,進入應用開發界面:
然後輸入 chatgpt 並回車進行搜索,選擇第一個搜索結果,保存並重啓:
重啓之後,自定義依賴項中便出現了 chatgpt。
新建雲函數
然後我們點擊函數,函數列表右側的加號,新增一個可以接入微信公衆號的 ChatGPT 雲函數:
雲函數完整代碼如下:
// 引入crypto和cloud模塊
import * as crypto from 'crypto';
import cloud from '@lafjs/cloud';
const WAIT_MESSAGE = `處理中 ... \n\n請稍等3秒後發送【1】查看回復`
const NO_MESSAGE = `暫無內容,請稍後回覆【1】再試`
const CLEAR_MESSAGE = `✅ 記憶已清除`
const HELP_MESSAGE = `ChatGPT 指令使用指南
| 關鍵字 | 功能 |
| 1 | 上一次問題的回覆 |
| /clear | 清除上下文 |
| /help | 獲取更多幫助 |
`
// 不支持的消息類型
const UNSUPPORTED_MESSAGE_TYPES = {
image: '暫不支持圖片消息',
voice: '暫不支持語音消息',
video: '暫不支持視頻消息',
music: '暫不支持音樂消息',
news: '暫不支持圖文消息',
}
// 定義休眠函數
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
// 創建數據庫連接並獲取Message集合
const db = cloud.database();
const Message = db.collection('messages')
// 處理接收到的微信公衆號消息
export async function main(event) {
const { signature, timestamp, nonce, echostr } = event.query;
const token = '123456';
// 驗證消息是否合法,若不合法則返回錯誤信息
if (!verifySignature(signature, timestamp, nonce, token)) {
return 'Invalid signature';
}
// 如果是首次驗證,則返回 echostr 給微信服務器
if (echostr) {
return echostr;
}
// 處理接收到的消息
const payload = event.body.xml;
// console.log("payload",payload)
// 文本消息
if (payload.msgtype[0] === 'text') {
const newMessage = {
msgid: payload.msgid[0],
question: payload.content[0].trim(),
username: payload.fromusername[0],
sessionId: payload.fromusername[0],
createdAt: Date.now()
}
// 修復請求響應超時問題:如果 5 秒內 AI 沒有回覆,則返回等待消息
const responseText = await Promise.race([
replyText(newMessage),
sleep(4000.0).then(() => WAIT_MESSAGE),
]);
return toXML(payload, responseText);
}
// 公衆號事件
if (payload.msgtype[0] === 'event') {
// 公衆號訂閱
if (payload.event[0] === 'subscribe') {
return toXML(payload, HELP_MESSAGE);
}
}
// 暫不支持的消息類型
if (payload.MsgType in UNSUPPORTED_MESSAGE_TYPES) {
const responseText = UNSUPPORTED_MESSAGE_TYPES[payload.MsgType];
return toXML(payload, responseText);
}
return 'success'
}
// 處理文本回復消息
async function replyText(message) {
const { question, sessionId } = message;
console.log("replyText 執行了")
// 檢查是否是重試操作,如果是重試操作,返回上一次的回覆
if (question === '1') {
const lastMessage = await Message.where({
sessionId
}).orderBy("createdAt", "desc").get();
if (lastMessage.data[0]) {
return `${lastMessage.data[0].question}\n------------\n${lastMessage.data[0].answer}`;
}
return NO_MESSAGE;
}
// 獲取上下文 id
const res = await Message.where({
sessionId
}).orderBy("createdAt", "desc").getOne();
const parentId = res?.data?.parentMessageId
const conId = res?.data?.conversationId
// 發送指令
if (question.startsWith('/')) {
return await processCommandText(message);
}
// 獲取 OpenAI 回覆內容
const { error, answer, parentMessageId, conversationId } = await getOpenAIReply(question, parentId, conId);
if (error) {
console.error(`sessionId: ${sessionId}; question: ${question}; error: ${error}`);
return error;
}
// 將消息保存到數據庫中
const token = question.length + answer.length;
const result = await Message.add({ token, answer, parentMessageId, conversationId, ...message });
console.debug(`[save message] result: ${result}`);
return answer;
}
// 獲取 OpenAI API 的回覆
async function getOpenAIReply(question, parentId, conId) {
console.log("getOpenAIReply 執行了")
// 引入 ChatGPTUnofficialProxyAPI 模塊
const { ChatGPTUnofficialProxyAPI } = await import('chatgpt')
// 創建 ChatGPTUnofficialProxyAPI 實例
const api = new ChatGPTUnofficialProxyAPI({
accessToken: cloud.env.ACCESSTOKEN,
apiReverseProxyUrl: "https://bypass.churchless.tech/api/conversation"
})
try {
// 如果有上下文 id,就帶上
let res;
if (parentId && conId) {
res = await api.sendMessage(question, { conversationId: conId, parentMessageId: parentId })
} else {
res = await api.sendMessage(question)
}
// 返回 OpenAI 回覆的內容及上下文 id
return { answer: res.text.replace("\n\n", ""), parentMessageId: res.parentMessageId, conversationId: res.conversationId }
} catch (e) {
console.log(e)
return {
error: "問題太難了 出錯了. (uДu〃).",
}
}
}
// 校驗微信服務器發送的消息是否合法
function verifySignature(signature, timestamp, nonce, token) {
const arr = [token, timestamp, nonce].sort();
const str = arr.join('');
const sha1 = crypto.createHash('sha1');
sha1.update(str);
return sha1.digest('hex') === signature;
}
// 返回組裝 xml
function toXML(payload, content) {
const timestamp = Date.now();
const { tousername: fromUserName, fromusername: toUserName } = payload;
return `
<xml>
<ToUserName><![CDATA[${toUserName}]]></ToUserName>
<FromUserName><![CDATA[${fromUserName}]]></FromUserName>
<CreateTime>${timestamp}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[${content}]]></Content>
</xml>
`
}
async function processCommandText({ sessionId, question }) {
// 清理歷史會話
if (question === '/clear') {
const res = await Message.where({ sessionId }).remove({ multi: true })
return CLEAR_MESSAGE;
} else {
return HELP_MESSAGE;
}
}
由於 OpenAI 的 API Key 需要充值才能用,所以我們選擇劍走偏鋒,直接使用 ChatGPT 網頁版。但是國內環境無法訪問 ChatGPT,所以我們需要一個 Proxy。不用擔心,國外已經有熱心小哥給我們提供了公共的 Proxy,我們只需要直接調用就好啦!
詳情可參考 ChatGPTUnofficialProxyAPI 的使用文檔。
只要你有 ChatGPT 賬號,都可以使用這種方法,最🐮🍺的是,你可以直接在 Laf 的國內環境 https://laf.run 中使用!!!
核心函數:
getOpenAIReply
函數通過引入ChatGPTUnofficialProxyAPI
模塊,創建實例並調用其方法,獲取 ChatGPT 的回覆內容。verifySignature
函數用於校驗微信服務器發送的消息是否合法。toXML
函數將回復內容組裝成XML格式。processCommandText
函數用於處理指令,目前支持清除歷史會話和獲取幫助信息兩個指令。
注意:
token
要與微信公衆號中設置一致。ACCESSTOKEN
的獲取方式:你需要先在瀏覽器中登錄 ChatGPT 網頁版,然後在瀏覽器中訪問這個 URL:https://chat.openai.com/api/auth/session,瀏覽器會返回一個 JSON,裏面包含了 accessToken 字段,將這個字段的值複製即可。
雲函數寫完之後就點擊發布,左側的接口地址要保存一下,稍後將在微信公衆號中使用此地址。
配置微信公衆號
這一步我們需要在微信公衆號平臺上配置開發者信息,並將服務器地址設置爲部署好的雲函數服務地址。步驟如下:
首先你需要有一個公衆號,然後登錄微信公衆平臺,點開左側的「設置與開發」,點擊「基本設置」,然後點擊「服務器配置」,服務器配置那裏點擊修改配置:
將雲函數服務地址複製到「服務器 URL」中,下邊的 Token 與雲函數代碼中的 token 保持一致,下邊的 EncodingAESKey 點擊右側隨機生成就行,然後點擊提交:
返回 token 校驗成功後,點擊「啓用」即可。
現在你已經完成了所有必要的設置和配置,下面就可以直接進入微信公衆號「Laf 開發者」後臺與機器人進行交互啦!
ChatGPT 機器人可以回答用戶提出的問題,並且可以根據用戶提供的上下文進行回覆。以下是一些指令和關鍵字,可以幫助您更好地使用 ChatGPT 機器人:
- 【1】:獲取上一次問題的回覆。
- /clear:清除上下文。
- /help:獲取更多幫助。 除了以上指令和關鍵字外,你還可以根據自己的需求進行定製化開發,以滿足用戶的需求。
總結
通過以上步驟,您已經成功地將 ChatGPT 接入微信公衆號,並使用 Laf 平臺來部署 ChatGPT 雲函數。這樣,您就可以在公衆號中爲您的用戶提供智能問答、聊天機器人等服務了,微信公衆號自帶的自動回覆功能可以拋棄了。
當然,直接接入 ChatGPT 網頁版肯定沒有接入 API 穩定,如果你想通過 API 的方式接入,可以參考原作者的官方倉庫:
最後,歡迎關注我們的公衆號直接與 ChatGPT 對話吧!