單純使用 ChatGPT API 做出來的 LINE BOT,通常不具備閱讀歷史紀錄來讓上下文連貫的功能,但如果搭配 Firebase Realtime database 作為資料庫,就能將過去聊天的歷史紀錄作為訊息內容,讓 LINE BOT 也能具備連貫上下文的功能,這篇教學會介紹如何實作這個應用。
要實作本篇文章的範例,需要參考下列文章,建立 Firebase Realtime database 以及熟悉相關技術。
參考「自動回覆訊息」文章,使用 Anaconda Jupyter 或本機環境執行下方的程式碼,並搭配 ngrok 服務,建立 LINE Webhook URL,執行後發送訊息到 LINE BOT,應該就能看到 LINE BOT 回覆一模一樣的訊息。
from flask_ngrok import run_with_ngrok
from flask import Flask, request
from linebot import LineBotApi, WebhookHandler
from linebot.models import TextSendMessage, ImageSendMessage
import json, requests
import openai
openai.api_key = '你的 OpenAI API KEY' # 你的 OpenAI API KEY
from firebase import firebase
url = 'https://XXXXXXXXXXXX.firebaseio.com' # 你的 Firebase Realtime database URL
fdb = firebase.FirebaseApplication(url, None) # 初始化 Firebase Realtime database
app = Flask(__name__)
@app.route("/", methods=['POST'])
def linebot():
body = request.get_data(as_text=True)
json_data = json.loads(body)
print(json_data)
try:
token = 'LINE Access Token' # 你的 Access Token
secret = 'LINE Channel Secret' # 你的 Channel Secret
line_bot_api = LineBotApi(token)
handler = WebhookHandler(secret)
signature = request.headers['X-Line-Signature']
handler.handle(body, signature)
tk = json_data['events'][0]['replyToken'] # 回覆的 reply token
timestamp = json_data['events'][0]['timestamp'] # 訊息時間戳
msg_type = json_data['events'][0]['message']['type'] # 訊息類型
# 如果是文字訊息
if msg_type == 'text':
msg = json_data['events'][0]['message']['text'] # 取出文字內容
chatgpt = fdb.get('/','chatgpt') # 讀取 Firebase 資料庫內容
if chatgpt == None:
messages = [] # 如果資料庫裡沒有內容,建立空串列
else:
messages = chatgpt # 如果資料庫裡有內容,設定歷史紀錄為資料庫內容
if msg == '!reset':
fdb.delete('/','chatgpt') # 如果收到 !reset 的訊息,表示清空資料庫內容
reply_msg = TextSendMessage(text='對話歷史紀錄已經清空!')
else:
messages.append({"role":"user","content":msg}) # 如果是一般文字訊息,將訊息添加到歷史紀錄裡
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
max_tokens=128,
temperature=0.5,
messages=messages
)
ai_msg = response.choices[0].message.content.replace('\n','') # 移除回應裡的換行符
messages.append({"role":"assistant","content":ai_msg}) # 歷史紀錄裡添加回應訊息
fdb.put_async('/','chatgpt',messages) # 使用非同步的方式紀錄訊息
reply_msg = TextSendMessage(text=ai_msg) # 回應訊息
line_bot_api.reply_message(tk,reply_msg)
else:
reply_msg = TextSendMessage(text='你傳的不是文字訊息呦')
line_bot_api.reply_message(tk,reply_msg)
except:
print('error')
return 'OK'
if __name__ == "__main__":
run_with_ngrok(app)
app.run()
參考「使用 Cloud Functions 建立 Webhook」教學,建立並進入 Google Cloud Functions 專案,點擊 requirements.txt,輸入下列資訊。
# Function dependencies, for example:
# package>=version
line-bot-sdk
requests
openai
git+https://github.com/ozgur/python-firebase
將下列的程式碼貼入 main.py,輸入自己的 LINE Access Token、Channel Secret、OpenAI API Key、Firebase 網址。
from linebot import LineBotApi, WebhookHandler
from linebot.models import TextSendMessage, StickerSendMessage, ImageSendMessage, LocationSendMessage
import requests, json
import openai
openai.api_key = 'API KEY'
from firebase import firebase
token = '你的 Access Token'
secret = '你的 Channel Secret'
def linebot(request):
body = request.get_data(as_text=True)
json_data = json.loads(body)
try:
line_bot_api = LineBotApi(token)
handler = WebhookHandler(secret)
signature = request.headers['X-Line-Signature']
handler.handle(body, signature)
tk = json_data['events'][0]['replyToken']
timestamp = json_data['events'][0]['timestamp']
msg_type = json_data['events'][0]['message']['type']
if msg_type == 'text':
msg = json_data['events'][0]['message']['text']
url = 'XXXXXXXXXXX.firebaseio.com'
fdb = firebase.FirebaseApplication(url, None)
chatgpt = fdb.get('/','chatgpt')
if chatgpt == None:
messages = []
else:
messages = chatgpt
if msg == '!reset':
reply_msg = TextSendMessage(text='對話歷史紀錄已經清空!')
line_bot_api.reply_message(tk,reply_msg)
fdb.delete('/','chatgpt')
else:
messages.append({"role":"user","content":msg})
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
max_tokens=128,
temperature=0.5,
messages=messages
)
ai_msg = response.choices[0].message.content.replace('\n','')
messages.append({"role":"assistant","content":ai_msg})
reply_msg = TextSendMessage(text=ai_msg)
line_bot_api.reply_message(tk,reply_msg)
fdb.put_async('/','chatgpt',messages)
else:
reply_msg = TextSendMessage(text='你傳的不是文字訊息呦')
line_bot_api.reply_message(tk,reply_msg)
except Exception as e:
detail = e.args[0]
print(detail)
return 'OK'
部署成功後會看到綠色勾勾,複製觸發網址,回到 LINE Developer 裡更新 Webhook URL。
回到 LINE 開始與 LINE BOT 聊天,就會發現 LINE BOT 會記得之前的聊天內容,並根據之前的聊天內容進行回覆。
一旦 LINE BOT 搭配 OpenAI ChatGPT 可以根據聊天記錄進行回覆,就會更有和真人聊天的感覺,但相對了開始傳送聊天記錄後,訊息 token 就會暴增,當免費額度用光之後就要開始付費囉。
大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我有個超過一千篇教學的 STEAM 教育學習網,有興趣可以參考下方連結呦~ ^_^