iT邦幫忙

2023 iThome 鐵人賽

0
Software Development

跟著 OXXO 一起學 Python系列 第 100

( Day 47.3 ) Python LINE BOT 串接 OpenAI ChatGPT ( 上下文歷史紀錄 )

  • 分享至 

  • xImage
  •  

單純使用 ChatGPT API 做出來的 LINE BOT,通常不具備閱讀歷史紀錄來讓上下文連貫的功能,但如果搭配 Firebase Realtime database 作為資料庫,就能將過去聊天的歷史紀錄作為訊息內容,讓 LINE BOT 也能具備連貫上下文的功能,這篇教學會介紹如何實作這個應用。

本篇文章所需知識

要實作本篇文章的範例,需要參考下列文章,建立 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()

LINE BOT 教學 ( Python )- 串接 OpenAI ( 上下文歷史紀錄 ) - 本機環境或 Colab

部署到 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

LINE BOT 教學 ( Python )- 串接 OpenAI ( 上下文歷史紀錄 ) - requirements.txt

將下列的程式碼貼入 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 BOT 教學 ( Python )- 串接 OpenAI ( 上下文歷史紀錄 ) - 部署到 Google Cloud Functions

回到 LINE 開始與 LINE BOT 聊天,就會發現 LINE BOT 會記得之前的聊天內容,並根據之前的聊天內容進行回覆。

LINE BOT 教學 ( Python )- 串接 OpenAI ( 上下文歷史紀錄 ) - 部署到 Google Cloud Functions

小結

一旦 LINE BOT 搭配 OpenAI ChatGPT 可以根據聊天記錄進行回覆,就會更有和真人聊天的感覺,但相對了開始傳送聊天記錄後,訊息 token 就會暴增,當免費額度用光之後就要開始付費囉。

更多教學

大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我有個超過一千篇教學的 STEAM 教育學習網,有興趣可以參考下方連結呦~ ^_^


上一篇
( Day 47.2 ) Python LINE BOT 串接 OpenAI ChatGPT ( 翻譯機器人 )
下一篇
( Day 48 ) 「跟著 OXXO 一起學 Python」完賽心得
系列文
跟著 OXXO 一起學 Python101
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言