繼上次說明完了FastAPI是什麼?並且如何運用FastAPI部署一個GCR雲端的微服務,如果還沒看過的朋友可以參考這篇FastAPI微服務與GCR雲端部署教學。這次就來實際介紹要如何運用FastAPI串接 Google Gemini ,結合google Firebase儲存對話紀錄,編寫一個有記憶功能的LineBot的聊天機器人。

Line Bot 簡介

Line Bot 是一款能透過LINE平台與使用者互動的聊天機器人。它作為官方帳號的角色,可以協助企業或個人建立與客戶之間便利的溝通管道,並且自動化處理許多日常業務和服務。Line Bot 已經被運用到各式的店家與場域,例如各種餐飲店的訂位訂餐平台,或是各個政府機關所建立的旅遊推廣資訊。透過Line Bot,使用者可以部分的取代傳統的應用程式與網頁資訊系統,便可以整合各種不同店家或官方帳號,並輕鬆地查詢商品資訊、訂餐、預約、付款、客服等等,不需要等待人工客服回覆,大大的降低了人工的需求。

創建LineBot

要創建linebot非常的簡單,首先登入Line Developer,點選 "Log in to Console",如果只是要開發測試用的linebot可以使用自己的帳號登入,若有正式官方帳號,可以依自己的需求使用!

  1. 點選 Products,並選擇Message API Alt text

  2. start now Alt text

  3. 設定基本資料 Alt text 這裡的基本資料就照自己的需求填寫即可,總之就按照它的提示,不該留空白的就盡量掰一些符合的內容這樣,也不用太有壓力,反正只是建立測試用的line bot,有些基本資料之後都還可以修改!!!

  4. 取得Channel secret、Channel access token 建立完LineBot後,可以在Basic Setting頁面中找到Channel secret、在Messaging API頁面中找到 Channel access token,這兩個東西簡單來說就是連接自己Line帳號的身份證和鑰匙,你會隨便把你家的鑰匙交給別人嗎??肯定是不會嘛,所以將這兩串密碼複製下來後貼進 .env的檔案中妥善保管,小心不要外流或是不小心上傳到git喔。 Alt text Alt text

到這裡,目前就OK了,之後要做的就將部署完的API URL貼到Messaging API頁面中的Webhook URL,以達成與透過API與Line溝通的目的。下圖說明了line bot 與 Python API的關係。 Alt text (來源:STEAM 教育學習網)

Google Gemini

我們的目的是編寫一個Python FastAPI的程式,串接Google Gemini等GPT形式的語言模型API,並利用Line Webhook達成在Line聊天室與 GPT Model的目的。所以開通Google Gemini的API服務就是相當必要的。至於為何不是串接目前最火紅的OpenAI,所推出的ChatGPT,我其實兩個model都有實作過,但我的Chat GPT的API試用到期了,啊我又懶得再創一個GPT帳號 所以我就選擇有更多免費額度和擴充服務選項的Gemini進行開發。

Get Gemini API Key

其實和Chat GPT類似,取得API Key的方式都非常簡單。進入Google AI for Developer平台,點選 “Get API Key in Google AI Studio”。 Alt text

登入 Google AI Studio 平台後,點選 “Get API Key" 。 Alt text

接著就可以取得API Key嘍! Alt text

PS. 取API key的過程中可能會需要選擇GCP的相關資訊,如果有GCP開發經驗的朋友相信不陌生;若沒有經驗的朋友也不用緊張,網路上有相當多的資源,簡而言之GCP平台上的專案資訊整合的相當好,可以按照自己的測試需求進行選擇,也可以參考我前幾篇使用GA與GCR的文章,流程都大同小異!

Google Cloud Firebase

如果有串連過Chat GPT API的朋友應該會發現,若只是單純的對API操作,會發現每次的對話都是獨立的事件,GPT無法記得先前的對話內容,因此直接套用Chat GPT API進入line bot 就會發現聊天室的對話內容牛頭不對馬嘴,效果相當差。因此,便需要一個適當的儲存空間將對話紀錄儲存,並做為參數傳入每次的對話中,而FireBase就是一個相當不錯的選擇,可以透過其 Realtime Database 儲存對話資訊,以達成延續對話的目的。

Realtime Database

FireBase 作為GCP平台產品的一員,自然與其他的服務有相當高的整合性,操作邏輯等也都相當雷同。在登入後,建立一個project(如果有建立過或測試的專案可直接選擇),接著進行一些基本資訊的設定就完成了。 Alt text

接著點擊專案,在左側的“構建”中找到“RealTime Database”,建立一個沒有權限限制的realtime database,這樣的設定可以讓任何人存取與修改(請注意: 這是因為做測試專案,請勿在正式專案如此設定)。 Alt text

最後取得資料庫的網址,格式如下: https://XXX.firebaseio.com/

Deploy And Test

LineBot Template

關於如何建立一個基於Fast API 的 Line Bot,可以參考這個GitHub Repository,其中大部分的內容是源於Fawen Yo 大大 的這篇,但針對發佈的平台和一些細節設定做一些調整。簡而言之,這個line bot的範本是建立一個echo的對話機器人,會不斷repeat使用者傳出的訊息。那意下我將以我的範本進行說明,各位可以自行取用。

Code

串接Gemini與Firebase 其實相當簡單,只需要修改上述提供的範本的些許地方。

  1. 打開範本,進入projecty 資料夾的 .env 檔案,填入先前複製好的key(LINE, Gemini, FireBase) 。

    LINE_CHANNEL_SECRET = "YOUR_API_KEY"
    LINE_CHANNEL_ACCESS_TOKEN = "YOUR_API_KEY"
    GEMINI_KEY  = "YOUR_API_KEY"
    FIREBASE_URL = "YOUR_API_KEY"
    
  2. 接著在 config.py 的檔案中讀取上述的Key。

    import os
    from dotenv import load_dotenv
    # Load environment variables
    load_dotenv()
    # LINE Bot 設定
    LINE_CHANNEL_SECRET = os.environ.get("LINE_CHANNEL_SECRET")
    LINE_CHANNEL_ACCESS_TOKEN = os.environ.get("LINE_CHANNEL_ACCESS_TOKEN")
    GOOGLE_API_KEY = os.environ.get('GEMINI_KEY')
    FIREBASE_URL = os.environ.get('FIREBASE_URL')
    
  3. 最後進入line資料夾中,修改message_event.py。這個函式主要是在處理回覆什麼樣的訊息給使用者,所以想當然爾就是要修改這個函式,將使用者輸入的資料丟進Gemini API,取得回覆後傳遞給使用者並將對話紀錄儲存近firebase中。

    import sys
    import google.generativeai as genai
    from firebase import firebase
    from linebot import LineBotApi
    from linebot.models import TextMessage, TextSendMessage
    sys.path.append(".")
    import config
    line_bot_api = LineBotApi(config.LINE_CHANNEL_ACCESS_TOKEN)
    firebase_url = config.FIREBASE_URL
    genai.configure(api_key = config.GOOGLE_API_KEY)
    model = genai.GenerativeModel('gemini-pro')
    def handle_message(event) -> None:
     """Event - User sent message
    
     Args:
         event (LINE Event Object): Refer to https://developers.line.biz/en/reference/messaging-api/#message-event
     """
     user_id = event.source.user_id
     msg_type = event.message.type
     reply_token = event.reply_token
     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)
     # Text message
     if isinstance(event.message, TextMessage):
         # Get user sent message
         user_message = event.message.text
         if chatgpt is None:
                 messages = []
         else:
             messages = chatgpt
         if user_message == '!清空':
                 reply_msg = TextSendMessage(text='對話歷史紀錄已經清空!')
                 fdb.delete(user_chat_path, None)
         else:
             model = genai.GenerativeModel('gemini-pro')
             messages.append({'role':'user','parts': [user_message]})            
             response = model.generate_content(messages)
             messages.append({'role':'model','parts': [response.text]})                
             reply_msg = TextSendMessage(text=response.text)
             # 更新firebase中的對話紀錄
             fdb.put_async(user_chat_path, None , messages)
         # Reply with same message
         #messages = TextSendMessage(text=user_message)
    
         # Reply with AI Reply
         line_bot_api.reply_message(reply_token=reply_token, messages=reply_msg)
    

Testing with Ngrok

到這裡其實已經完成了90%了,若只是想要測試這個linebot的功能性,可以利用ngrok來進行測試。簡單來說,ngrok可以將你在本機run 起來的 api 或 web服務(i.e. localhost:8000)轉為https開頭的暫時對外服務網址,可以讓所有人該網址訪問localhost:8000。

使用的方法很簡單,只需要下載ngrok,註冊/登入帳號後,執行以下命令,便可以將該port上的服務轉到特定的網址嘍!

ngrok http [port]

Alt text

最後將該網址貼在Line 的 Webhook setting 中。 Alt text 注意:由於路由設定的緣故,後面要加上"/callback"!

GCR 部署

方才各位可能是透過 uvicorn.run 建立local端的FastAPI 服務,並透過ngrok建立對外的服務網址,以便於line bot 的溝通。但這種方式終究只是暫時的!因此可以將整個服務打包成docker 並運行在GCR上!!!部署的方法與先前這篇提到的部署方法一模一樣。

這裡我習慣針對單一的container 進行部署,要利用docker-compose將整個專案打包應該也是可以的~~

cd project
gcloud run deploy [your_app_name] --source .

部署完成後跟ngrok測試方式一樣,將網址加上"/callback",貼上 Line Webhook就大功告成了。

成果

如果仔細看上面的程式碼,會發現有埋了一個“!清空”的關鍵字,可以將FireBase的對話紀錄刪除,進而將Gemini 模型初始化的目的,同時可以繼續進行其他的對話!!!! Alt text

boba-icon
請我喝珍奶!