串接 OpenAI ChatGPT (3)
单纯使用 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 就会暴增,当免费额度用光之后就要开始付费啰。
微信扫码关注
抖音扫码关注