【LineBot實作】如何製作有記憶的對話機器人

Pearl
11 min readDec 14, 2023

--

開始

要開始製作Line機器人前,我們先瞭解本篇文章會需要使用到的平台。

  1. Line Developers創建Line機器人
  2. OpenAI取得OpenAI API 的 secret key,讓機器人對話。
  3. Google Cloud Functions:Python程式碼的部署平台,生成供LineBot使用的webhook。
  4. Firebase:建立即時資料庫,讓機器人可以取得對話紀錄,進行有連續性、有記憶的對話。

Line Bot創建

Step.1 進入Line Developers創建一隻機器人

Step.2 設定機器人基本資料

一些必填的填一下就好~

  • Channel type :設定為 Messaging API (一定要!)
  • Provider:如果已經有了可以用以前的,沒有使用過可以新建立一個
  • 其他選項可以大致填一下
  • 機器人大頭貼可以上傳自己設定好的照片
  • Privacy policy URL、Terms of use URL:這兩個可以不用填

Step.3 獲得機器人的Channel secret、Channel access token

建立完機器人後,可以在那個機器人的Basic Setting頁面中找到Channel secret、在Messaging API頁面中找到 Channel access toke,這兩個東西會在程式中使用到。

如果按ISSUE、REISSUE,Line會重新給你secret和access token,記得要在程式中修改,不然程式會連接不到機器人。

P.S. Allow bot to join group chats、Auto-reply messages、Greeting messages可以依照需求修改。這邊先改為Disabled。

Step.4 完成機器人設定

好了!那我們先將機器人放到一邊,之後部署完程式再將URL貼回Messaging API頁面中的Webhook URL。

OpenAI API

這邊作者我主要是參考上面教學網站的教學完成的。在這裡只做重點提醒。

  1. 只要是有使用過Chat GPT的帳號都是已經註冊過的帳號,如果註冊超過三個月是沒有免費額度使用的。你只能乖乖付費🥲
  2. 只有建立完成的當下可以複製 API Keys,所以請使用記事本或其他工具儲存 API Key,如果要刪除 API Key,必須再次建立新的 API Key 才能刪除舊的。

Firebase

Step.1 開始

點選「Get Start」。

Step.2 建立專案

點選「新增專案」。

第二步的選項要打開Google Analytics喔~

Step.3 進入Realtime database

進入Realtime Database之後,建立資料庫。

這邊要選鎖定模式,建立完資料庫再修改。

當你看到的畫面和下圖一樣時,就完成資料庫建立。
會看到有一串URL:https://XXX.firebaseio.com/
這就是在程式中可以設定資料儲存位置的URL,先把它放到旁邊,等等會用到。

但還沒結束!!我們需要讓它設定成可以從外部寫入。

Step.4 更改規則

在「規則」的地方,把false都改成true,出現紅字是正常的,把提醒關掉就好。

那這樣就完成Firebase Realtime Database的設定了!

Google Cloud Functions

Step.0 淺談Google Cloud

Google Cloud 是一系列由Google提供的雲端運算服務,包括:雲端運算、資料儲存、資料分析及機器學習等。使用 Google Cloud Functions的優點在於它不需要另架伺服器和環境,在小型的機器人使用上也有一定的免費額度可以使用,而且只有實際使用時才計算額度,對於只是想要試做看看的開發者而言相對友善。

Step.1 開始

點選網站頁面上的「控制台」或「開始試用」。

啟用Google Cloud Functions需要綁定個人信用卡,如需要綁定教學的請參考這裡

Step.2 進入Cloud Functions建立專案

在選單中尋找Cloud Functions,如果找不到它的話,可以看看「無伺服器」這個分類下有沒有。

然後點選「建立專案」。

Step.3 建立函式

環境設定為第一代。地區可以設定為asia-east1台灣

觸發條件設定為HTTP,並且允許未經驗證的叫用,再按儲存

點開「執行階段、建構作業、連線和安全性設定」,往下滑新增「執行階段環境變數

新增四個環境變數

  1. OPENAI_API_KEY:(在OpenAI獲得的secret key)
  2. LINE_BOT_TOKEN:(在Line Developers獲得的Channel access token)
  3. LINE_BOT_SECRET:(在Line Developers獲得的Channel secret)
  4. FIREBASE_URL:(在Firebase獲得的URL)

注意:變數名稱要和上方一模一樣,歡迎複製貼上,數值要貼自己的!!

按下一步,更改程式碼。

執行階段更改為「Python3.8」進入點改成「linebot」

main.py貼上下方程式碼

from linebot import LineBotApi, WebhookHandler
from linebot.models import TextSendMessage
import json
import os
from firebase import firebase
import openai

# 使用環境變量讀取憑證
openai.api_key = os.getenv('OPENAI_API_KEY')
token = os.getenv('LINE_BOT_TOKEN')
secret = os.getenv('LINE_BOT_SECRET')
firebase_url = os.getenv('FIREBASE_URL')

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)
event = json_data['events'][0]
tk = event['replyToken']
user_id = event['source']['userId']
msg_type = event['message']['type']

fdb = firebase.FirebaseApplication(firebase_url, None)
user_chat_path = f'chat/{user_id}'
chat_state_path = f'state/{user_id}'
chatgpt = fdb.get(user_chat_path, None)

if msg_type == 'text':
msg = event['message']['text']

if chatgpt is None:
messages = []
else:
messages = chatgpt

if msg == '!清空':
reply_msg = TextSendMessage(text='對話歷史紀錄已經清空!')
fdb.delete(user_chat_path, None)

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)
# 更新firebase中的對話紀錄
fdb.put_async(user_chat_path, None , messages)

line_bot_api.reply_message(tk, reply_msg)

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'

requirements.txt貼上下方套件需求:

# Function dependencies, for example:
# package>=version

line-bot-sdk
requests
openai==0.28
git+https://github.com/ozgur/python-firebase

注意:不用再新增Flask套件,因為Cloud Functions本來就是Flask框架!

修改完成,就開始部署
(每次部署都需要億點時間,等它從繞圈變成綠勾勾就部署完成了)

Step.4 完成

部署完成後,可以在「觸發條件」中找到「觸發網址」,再把這個複製下來貼回LineBot。

回到Line Developers,找到你的機器人,進入Messaging API,把Use webhook打開把觸發網址貼到Webhook URL,再按Verify,顯示Success就完成了!

成果查看

在firebase裡面也有儲存對話紀錄。

那我們就完成了有記憶的對話機器人!

Debug方向

這邊提供了一些錯誤的修正方式,如果發生錯誤可以試試看。

  1. Line的webhook verify後是success的,但是機器人沒有回應。
    → 程式錯誤,檢查程式是否有錯誤,環境變數是否正確設定。
  2. Cloud Functions的紀錄顯示Line的secret或access token認證不過。
    → 可能複製的時候按到issue,更改到secret或access token,再重新複製後更改程式的環境變數。
  3. 機器人對話一直是簡體中文。
    → 這是OpenAI的模型問題,不是程式問題(如果要改可以另外增加第三方軟體,完成翻譯成繁體中文的功能),可以在剛開始對話的時候,請機器人使用繁體中文。

--

--