LINE BOT 串接 OpenAI ChatGPT ( 上下文歷史紀錄 )
單純使用 ChatGPT API 做出來的 LINE BOT,通常不具備閱讀歷史紀錄來讓上下文連貫的功能,但如果搭配 Firebase Realtime database 作為資料庫,就能將過去聊天的歷史紀錄作為訊息內容,讓 LINE BOT 也能具備連貫上下文的功能,這篇教學會介紹如何實作這個應用。
快速導覽:
本篇文章所需知識
要實作本篇文章的範例,需要先參考以下文章,先建立自己的 LINE BOT 以及註冊 OpenAI 帳號。
參考下列文章,建立 Firebase Realtime database 以及熟悉相關技術。
本機環境或 Colab
參考「自動回覆訊息」文章,使用 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()
部署到 Google Cloud Functions
參考「使用 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 就會暴增,當免費額度用光之後就要開始付費囉。
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~