[Gemma] 用 GEMMA/LLAMA 這類 Local Model 打造更安全與具有隱私概念的 LINE ChatBot

卡通風格,一個聊天機器人同時握手 Alpaca  跟 大企業穿著西裝的上班族 。三個人一起握手

前言

LLM 的盛行之後,我們可以看到許多開發者將 LLM 整入到自己的聊天機器人 (LINE ChatBot) 之中。但是隨著而來也有不同的考量開始出現。讓許多開發者感到困擾,該如何更有經濟效益,並且更安全合法規的方式來使用 LINE Chatbot。

自從 LLAMA 等開源模型發展後,我們可以看到市面上有許多相關的開源模型。 LLAMA, Gemma, Phi3 等等,甚至有許多模型是可以在自己本地端的電腦中使用的。本篇文章將介紹這一類型的 Local Model 究竟能如何跟 LINE Bot 去整合,,並且提供一些範例程式碼作為 LINE Bot 的範例。

相關程式碼

關於 LINE Bot 相關程式碼,可以參考這一段。這邊使用 Groq 的 API 服務

https://github.com/kkdai/linebot-gemma

Gemma/LLAMA 這一類的模型該如何部署

不論是 Gemma 還是 LLAMA 這一類可以部署在本地電腦(或是自己的雲端伺服器裡面的),在本文中都先暫且稱為 Local Model 。 他的基本 Prediction 的精準度,在於你提供的本地機器的算力。

筆電使用上 可以考慮使用 Ollama

ollama-webui · GitHub

Ollama 是一個跨平台很好使用 LLM 的本地端工具,可以在本地端的電腦去使用 Llama3, Phi 3, Mistral, Gemma2 等等本地端的模型。使用跟安裝也相當簡單,基本上現在只要是 M1 或是 M2 的 Mac Book 就可以很輕鬆地跑起相關的服務。

GCP / Vertex AI 上面要部署這些模型

img

可以透過 Vertex AI 的服務來部署

但是需要申請伺服器單位如列表

Gemma / Gemma2 PaliGemma
Machine type: ct5lp-hightpu-4t Accelerator
type: TPU_V5_LITEPOD
Accelerator count: 4
- Machine type: g2-standard-16
- Accelerator type: NVIDIA_L4
- Accelerator count: 1

不過要注意這些單位需要申請,因為筆者還沒有申請下來本文將使用 Groq 來示範。 (2024/07/19)

透過 LPU API Services - Groq 來使用 Gemma2

image-20240725011545782

不得不說 Groq 真的很快,而且目前也都還有免費額度可以使用 API 來呼叫。這邊也放上最簡的程式碼來呼叫 Gemma2-9B

# Default
import os

from groq import Groq

client = Groq(
    # This is the default and can be omitted
    api_key=os.environ.get("GROQ_API_KEY"),
)

chat_completion = client.chat.completions.create(
    messages=[
        {
            "role": "system",
            "content": "you are a helpful assistant."
        },
        {
            "role": "user",
            "content": "Explain the importance of fast language models",
        }
    ],
    model="gemma2-9b-it",
)

print(chat_completion.choices[0].message.content)

如何跟 LINE Chatbot 可以有完美的結合?

Gemma 與 LLAMA 這種本地端模型有哪些優勢?

卡通風格, 個人資料的保護者,

個人隱私的去除

雖然說, OpenAI, Azure 甚至是 GCP 都有明令說 API Level 的資料是不可以拿來訓練的。但是根據許多個人資料保護法來說,最重要的就是不能隨便地將客戶的個人資料直接交給第三方的服務。 通常這一類型的服務被稱為 Personal Identifiable Information (PII) Redactor (PIID)。當然市面上有許多根據 REGEX 打造出來的 Redactor ,但是使用 LLM 可以很有效地去除。也能避免掉許多各種逃逸字元造成 REGEX 失敗的案例。

這時候就可以透過這一類的 local model 來將個人資料做拔除, 以下做一些簡單的 Code Sample

remove_personal_prompt = '''
Replace personal information, name with someone, address, ID number, bank account, etc. 
Just give me the modified original text, don't reply to me.
------\n
'''

這一段是移除個人資料的 prompt ,透過 LLM 可以很輕鬆的移除掉個人資料。 但是以往這件事情,如果是透過 Gemini 或是 OpenAI 的 API 來實作的話。那麼相關的資料流程會需要經過相關單位的資料審核,但是如果這個模型是透過本地端模型,就沒有這樣的困擾。

    msg = event.message.text
    
    # 透過本地端 LLM 來處理可能含有個人隱私的資訊。
    safe_ret = generate_local_llm_result(f'{remove_personal_prompt}, {msg}')
    
    # 比較安全的內容在傳遞到遠端的 LLM 來生成內容
    ret = generate_gemini_text_complete(f'{safe_ret}, reply in zh-TW:')
    reply_msg = TextSendMessage(text=ret.text)
    await line_bot_api.reply_message(
        event.reply_token,
        reply_msg
    )

這時候使用者雖然在不經意的狀況下,輸入資料到聊天視窗。但是因為透過了 generate_local_llm_result() ,會將裡面有個人資料的文字在本地端的模型(Gemma or LLAMA) 去除後,就可以將需求傳到外部的大型語言模型去進行接下來的相關處理。

測試結果範例(示意圖):

image-20240725100415967

根據這個範例,你可以看到使用者可能在無意間將自己的個人資訊(包括了信用卡帳號,銀行帳號)加入他詢問的問題中。這時候如果直接將使用者文字傳遞給第三方的 LLM ,在許多國家的資安控管上都是不合規訂的。 這時候要透過 local LLM 將原本資料去修改,將個人資料修改或是遮蓋後才能傳遞給第三方 LLM 。

相關程式碼: https://github.com/kkdai/linebot-gemma

判別是否需要 LLM 的協助

卡通風格, 一個機器人總機人員

聊天機器人搭配著 LLM 是一個強大的應用。但是如果每一句每一個訊息都傳遞到 LLM 那麼也太沒有效率了, 許多聊天機器人的開發人員都會了這個方法苦惱中。以往的方式可能用一些特殊的 prefix 來處理,但是這樣的處理方式相當的不友善也讓人好像回到 LLM 時代之前。

image-20240722205407728

就像是客服也不需要參與所有的對話,有些時候一些聊天的對話其實也不需要傳遞給 LLM 。這時候可以透過本地端的模型來幫助你。由於本地端的模型,可以透過比較小的模型,來讓成本整個降低。(並且小成本可以做出簡單的判斷)。

need_bot_prompt = '''
Check the following text to see if it requires customer service assistance. 
Just answer YES/NO
------\n
'''

以上是讓本地端的小模型,讓他來幫你判斷的 prompt。主要是判斷是否需要客服的協助(如果你打造的是客服聊天機器人)。這時候即便是小模型,也可以很快速的回覆 YES / NO 。 以下提供整段的判斷程式碼。

# 處理在群組內的訊息,有時候可能訊息不是對 LINE Bot。
if event.source.type == "group":
    msg = event.message.text
    
    # 使用本地端模型來判斷是否需要 LLM 
    determine_ret = generate_local_llm_result(f'{need_bot_prompt}, {msg}')

    # 檢查判斷的結果,如果是 YES 就直接將原文送到 LLM 。
    if "YES" in determine_ret:
        # Pass to LLM to process original request.
        ret = generate_gemini_text_complete(f'{msg}, reply in zh-TW:')
        reply_msg = TextSendMessage(text=ret.text)
        await line_bot_api.reply_message(
            event.reply_token,
            reply_msg
        )
    else:
        # 如果不需要,就 skip 這段訊息。
        continue

判斷是否需要 LLM 協助的範例

image-20240725100451360

根據這個範例,你可以看得出來。 除非你有特定想要詢問客服中心,不然都不會將訊息傳遞給 LLM 。這樣除了可以更節省經費之外,還可以不需要任何特殊字元來判斷是否需要 LLM 的幫助。

相關程式碼: https://github.com/kkdai/linebot-gemma

未來展望

Image

近期 (07/11) Uber 分享了他們的 GenAI Gateway 的創新 (Navigating the LLM Landscape: Uber’s Innovation with GenAI Gateway)(尤其是針對 LLM 的部分),裡面有提到通常來說訊息可能從許多地方進來

  • ChatBot
  • 3rd Party Library
  • Internal Services

但是這一類的訊息與請求在經過 GenAI Gateway 蛇後,會請過許多的處理。

  • PII Redaction (去除掉個人資訊)
  • 相關的資訊認證
  • 訊息與流量控管

最後才會分配到不同的 LLM 來處理相關的資訊。

在 LINE Bot 的開發上也是如此,雖然他的需求與功能會是單一且明確的。但是如果可以透過本地端的模型來讓使用者的體驗可以更好,卻也能讓成本取得一定程度的平衡。 這時候 LLM 不再是浪費錢的事情,而是一個完美的助手。

我們也期待著每一位開發者趕緊來試試看,並且跟我們分享相關的心得。

[Udacity] Gemini API by Google 課程分享

image-20240716202826521

(課程連結: https://www.udacity.com/enrollment/cd13416)

image-20240717155058420

前言

Google 跟 Udacity 合作開的這一個課程,蠻建議大家可以看一下。除了是免費之外,更加許多文件裡面沒有提供的詳細資訊跟用法講得很清楚。 想要更了解每一個 API 該如何使用,可以考慮看看。

這邊快速講一下課程大綱,然後帶幾個我覺得很重要的概念:

課程大綱

  • Introduction to LLMs and Gemini
    • 基本概念補充。
  • Introduction to prompting in Google AI Studio
    • 主要都是 AI Studio 的操作說明。
  • Developing with the Gemini API
    • 建議開發者都要看這個,大多是 API 使用細節。
  • Advanced Applications
    • 課程整理,還有相關小專案給學員練習。

幾個重點整理:

如何算產出 token

token_n_model = genai.GenerativeModel(model_name, generation_config={"temperature": 0.0})
poem_prompt = "Write me a poem about Berkeley's campus"

prompt_token_count = token_n_model.count_tokens(poem_prompt)
output_token_count = token_n_model.count_tokens(response.text)
print(f'Tokens in prompt: {prompt_token_count} \n Estimated tokens in output {output_token_count}')

透過

  • prompt_token_count: 輸入的 token 數字。
  • output_token_count: 產出的 token 數字。

Safety Setting

由於 Gemini 有著嚴格的管控,許多時候一些資料會被以安全因素而拒絕回覆。這時候你需要做一些處理:

在進行此演示之前,請記住要負責任地處理 AI 並遵循道德準則。

安全性是 Gemini 的一個重要內建功能。讓我們來了解更多它的功能:

如何檢查您的提示是否被安全過濾器阻擋

  • 哪些安全過濾器導致了阻擋
  • 如何調整設置以解除阻擋

檢查提示是否被阻擋

假設我們選擇了以下提示,在當前的安全設置下,您可以預期您的回應會被阻擋:

model = genai.GenerativeModel("gemini-1.5-flash", generation_config={"temperature": 0})

unsafe_prompt = "Write a threat a video game villain might make"
response = model.generate_content(unsafe_prompt)
print(response.text)

輸出:ValueError: 無效操作:response.text 快速訪問器需要回應包含有效的 Part,但沒有返回任何內容。請檢查 candidate.safety_ratings 以確定回應是否被阻擋。

現在,您可以印出 response.candidates[0].finish_reason 以進一步調查。

  • 如果 finish_reasonFinishReason.STOP,則表示您的生成請求成功運行。
  • 如果 finish_reasonFinishReason.SAFETY,則表示您的生成請求因安全原因被阻擋,因此 response.text 結構將為空。

檢查安全過濾器

印出 response.candidates[0].safety_ratings 將顯示評級結構。我們可能會看到如下內容:

[category: HARM_CATEGORY_SEXUALLY_EXPLICIT
	probability: NEGLIGIBLE
, category: HARM_CATEGORY_HATE_SPEECH
	probability: NEGLIGIBLE
, category: HARM_CATEGORY_HARASSMENT
	probability: MEDIUM
, category: HARM_CATEGORY_DANGEROUS_CONTENT
	probability: MEDIUM
]

在這裡,我們的提示觸發了 HARM_CATEGORY_HARASSMENTHARM_CATEGORY_DANGEROUS_CONTENT 類別,概率為中等,這就是為什麼我們被阻擋無法看到輸出。

如何移除過濾器

response = model.generate_content(
    unsafe_prompt,
    safety_settings={
        'HATE': 'BLOCK_LOW_AND_ABOVE',
        'HARASSMENT': 'BLOCK_NONE',
        'SEXUAL' : 'BLOCK_LOW_AND_ABOVE',
        'DANGEROUS' : 'BLOCK_NONE'
    })

這樣即便要產生一些具有髒話或是攻擊性文字也是被允許的。

透過 code execution 可以讓幻覺更少

可以讓 Gemini 幫你產生 Python code 並且實際執行它 (範例),對於一些數學(或是難以計算的數字)可以透過執行程式碼的方式來實際運算。 主要原因,因為如果你直接問 Gemini 可能因為幻覺造成計算出錯誤的數學結果,這時候務必要使用 code execution 來計算。

import os
import google.generativeai as genai

genai.configure(api_key=os.environ['API_KEY'])

model = genai.GenerativeModel(
    model_name='gemini-1.5-pro',
    tools='code_execution')

response = model.generate_content((
    'What is the sum of the first 50 prime numbers? '
    'Generate and run code for the calculation, and make sure you get all 50.'))

print(response.text)

透過 response_mime_type 強制回覆 JSON

雖然使用 prompting 可以要求 Gemini 回覆 JSON,但是為了確保回覆的資料格式,可以使用 response_mime_type 來強至指定回覆格式。

model = genai.GenerativeModel('gemini-1.5-flash',
                              generation_config={"response_mime_type": "application/json"})

prompt = """
  List 5 popular cookie recipes.

  Using this JSON schema:

    Recipe = {"recipe_name": str}

  Return a `list[Recipe]`
  """

response = model.generate_content(prompt)
print(response.text)

response_schema更可以限制回傳的資料格式,可以是 list or map 。

result = model.generate_content(
  "List 5 popular cookie recipes",
  generation_config=genai.GenerationConfig(response_mime_type="application/json",
                                           response_schema = list[Recipe]))

print(result.text)

[Google Cloud/Firebase] 關於 Python Firebase Admin 認證方式

前提

將 Python Firebase 的套件改成官方的 FirebaseAdmin ,以下有兩種認證方式。

透過 GOOGLE_CREDENTIALS

  • 將 services_account.json 放在環境變數 GOOGLE_CREDENTIALS
  • 透過以下程式碼啟動
  • 這個方式可以在本地端,遠端連線去 firebase 測試。
# 从环境变量中读取服务账户密钥 JSON 内容
service_account_info = json.loads(os.environ['GOOGLE_CREDENTIALS'])
# 使用服务账户密钥 JSON 内容初始化 Firebase Admin SDK
cred = credentials.Certificate(service_account_info)

# 啟動 firebase realtime database (透過 firebase_url )
firebase_admin.initialize_app(cred, {'databaseURL': firebase_url})

透過 GCP 系統啟動

  • 如果服務是部署在 Cloud Function 或是 Cloud Run
  • 其實可以透過預設的 Services Account 來取得相關權限
    • My Project 可以取得 My Project 在 firebase 的權限。
  • 這個設定方式如法在本地端連接到 Firebase 測試
# 直接取得 Google Cloud 的參數
cred = credentials.ApplicationDefault()

# 啟動 firebase realtime database (透過 firebase_url )
firebase_admin.initialize_app(cred, {'databaseURL': firebase_url})

增加 Firebase 相關安全性設定 (Firebase Realtime Database Security Rules)

{
  "rules": {
    ".read": "auth != null && auth.token.admin === true",
    ".write": "auth != null && auth.token.admin === true"
  }
}

這樣就可以了。

相關程式碼

放一些基本常用到的

查詢全部

def get_all_cards(u_id):
    try:
        # 引用 "namecard" 路径
        ref = db.reference(f'{namecard_path}/{u_id}')

        # 获取数据
        namecard_data = ref.get()
        if namecard_data:
            for key, value in namecard_data.items():
                print(f'{key}: {value}')
            return namecard_data
    except Exception as e:
        print(f"Error fetching namecards: {e}")

新增資料

def add_namecard(namecard_obj, u_id):
    """
    将名片数据添加到 Firebase Realtime Database 的 "namecard" 路径下。

    :param namecard_obj: 包含名片信息的字典对象
    """
    try:
        # 引用 "namecard" 路径
        ref = db.reference(f'{namecard_path}/{u_id}')

        # 推送新的名片数据
        new_ref = ref.push(namecard_obj)

        print(f'Namecard added with key: {new_ref.key}')
    except Exception as e:
        print(f'Error adding namecard: {e}')

移除重複資料

def remove_redundant_data(u_id):
    """
    删除 "namecard" 路径下具有相同电子邮件地址的冗余数据。
    """
    try:
        # 引用 "namecard" 路径
        ref = db.reference(f'{namecard_path}/{u_id}')

        # 获取所有名片数据
        namecard_data = ref.get()

        if namecard_data:
            email_map = {}
            for key, value in namecard_data.items():
                email = value.get('email')
                if email:
                    if email in email_map:
                        # 如果电子邮件已经存在于 email_map 中,则删除该名片数据
                        ref.child(key).delete()
                        print(f'Deleted redundant namecard with key: {key}')
                    else:
                        # 如果电子邮件不存在于 email_map 中,则添加到 email_map
                        email_map[email] = key
        else:
            print('No data found in "namecard"')
    except Exception as e:
        print(f'Error removing redundant data: {e}')

查詢某個資料是否已經存在

def check_if_card_exists(namecard_obj, u_id):
    """
    检查名片数据是否已经存在于 "namecard" 路径下。

    :param namecard_obj: 包含名片信息的字典对象
    :return: 如果名片存在返回 True, 否则返回 False
    """
    try:
        # 获取名片对象中的电子邮件地址
        email = namecard_obj.get('email')
        if not email:
            print('No email provided in the namecard object.')
            return False

        # 引用 "namecard" 路径
        ref = db.reference(f'{namecard_path}/{u_id}')

        # 获取所有名片数据
        namecard_data = ref.get()

        if namecard_data:
            for key, value in namecard_data.items():
                if value.get('email') == email:
                    print(
                        f'Namecard with email {email} already exists: {key}')
                    return True
        print(f'Namecard with email {email} does not exist.')
        return False
    except Exception as e:
        print(f'Error checking if namecard exists: {e}')
        return False

[Google Gemma2/PaliGemma] Gemma2/PaliGemma 學習筆記,可以應用範圍

Google AI Dev - Gemma2 && PaliGemma

img

這張圖稍微解釋了 Gemma 家族的兩個主要產品:

  • Gemma 2:也就是第二代的 Gemma
  • PaliGemma:是第一代的 VLM (視覺語言模型)

PaliGemma 相關資源:

  • 這邊有 paligemma 的 demo code (在 HuggingFace 上面)

    image-20240711212906507

    Google Chrome 2024-07-11 15.46.00

    可以看出來,由於是 Gemma 2B 加上 SigLIP 他對於語言的處理比較簡單。 可以做一些簡單的資訊處理,但是複雜問題就不行,比如說:

    • 產生 JSON 回覆 (X)
    • 一次回答兩個問題以上 (X)

    但是可以達到:

    • 用中文問問題(但是只會回答英文)
    • 可以做簡單的 OCR ,或是 Object Detection 。

    根據以下討論 PaliGemma 的影片, Google 團隊建議直接使用 Mix 版本的模型。他可以 Vision + Object Detection 。

image-20240711223813438

以上是 PaliGemma model 的相關 Benchmark ,可以看出來。

對比的相關測試數據跟方法,都可以得到不錯的準確率。

在 GCP 上面直接部署 PaliGemma

https://console.cloud.google.com/vertex-ai/publishers/google/model-garden/paligemma

另外一方面 Gemma 2 也可以: https://console.cloud.google.com/vertex-ai/publishers/google/model-garden/gemma2

image-20240712105925552

Gemma 可以適用的相關內容

透過 Gemma 可以讓 token 數字有大幅度的減少,有以下幾種方向可以考慮:

個人隱私的偵測

讓一些可能有個人隱私的部分可以獲得比較有效的篩選。

以前做法:

個人資料的偵測跟去除一直是一個很難的技術,需要有許多 regular expression 來做控管。即便是如此,還是有可能會有遺漏的地方。針對個人資料偵測這一段,其實在 LLM 是可以使用的。 但是在資安法規上,直接將用戶的個人資料傳到第三方,這樣是不符合規範的。所以這一段可以透過 Gemma 來施行。

如何用 Gemma (on-device LLM) 處理

查看以下內容是否包含個人資料,地址,身份字號,銀行帳號,回覆我 是 或是 否
------
我想找台北的房子

如何用 PaliGemma 處理?

Check if the image content contains personal information, address, identity number, or bank account number, and reply with Yes or No.

實地測試 - Gemma2 / PaliGemma

文字測試 Gemma2-9B

iTerm2 2024-07-12 11.49.58

改成 「某人」跟 「配偶」,並且可以有效地去除身份字號跟銀行帳號。

圖片測試 PaliGemma

Google Chrome 2024-07-12 11.10.02

image-20240712111911951

判定是否需要 「大型」LLM 的介入

將聊天機器人放入群組之中,最害怕的就是怕「 Token」爆掉。因為每一句話都需要判斷是否需要 LLM 的介入。這時候就可以透過 Gemma 可以有效的處理。

以前做法

有看過一些人做法是: 設定前綴字 "@" "!" 才會呼叫 LLM

這些做法沒有錯誤,只是這樣往往讓聊天室裡面的文字不好理解。

如何用 Gemma (on-device LLM) 處理

可以透過簡單的判斷 Prompt 讓

查看以下文字是否需要客服人員的協助。回答 yes/no
------
我今天早上吃了蛋餅

實體測試 Gemma

image-20240712122131249

未來展望

所謂的「小模型」或者是「Open Model」 不僅僅是在 on-device 的應用才有用。 放眼在 Cloud Services 的概念上,其實也是可以透過 on-devices LLM model 來做相關應用。 也歡迎大家一起來發想,如何透過比較隱密的 on-device model 來做出更多符合法規與讓成本更加優化的的應用。

[Google Gemma] Gemma2 bootcamp 公開資源紀錄

image-20240708123810509

懶人包:

懶人包: Gemma2 目前還是屬於偏大的參數(27B) 小模型還在訓練中,可以先看看 Gemma 1.1 。

相關內容

概論

Gemma Cookbook 資料分享

在 AI Studio 試試看 Gemma2

image-20240708125437847

Model Card

新增: Gemma2 on Groq (沒有很好顯卡,可以用這個範例)

新增: Gemma2 相關中文模型

image-20240708124404765

Q&A

  • Q: Gemma2 - Fine-Tunning 經驗?
    • HuggingFace 上面有註解,如果要 Fine-Tune 需要把 Attention 改成 Egar
  • Q: Gemma2 是否有 Embedding Model?
    • 目前還沒有。
  • Q: 有方式透過雲端方式直接使用 Gemma 嗎?不需要本地端部署 GPU?

[iThome Cloud Summit Lab][Python] 透過 Cloud Function (Cloud Run) + Firebase 與 Gemini Pro Vision 打造一個旅遊小幫手 LINE ChatBot

image-20240702204105183

LINE 2024-07-02 23.42.02

前言:

本篇文章主要是 iThome Cloud Summit 2024 Lab 的課程內容

這裡可以看一下投影片內容,在緊接著來看 Lab 實作的流程教學:

課程目標

這個工作坊適合對 ChatBot 開發、雲端服務或機器學習有興趣的開發者、學生或任何技術愛好者。無論你是想擴展你的技能集,還是對打造智能旅遊助手有獨特的想法,這個工作坊都將為你提供實踐經驗和深入知識。

課程綱要

第一部分:了解基礎

Cloud Function 和 Firebase 簡介:學習這些平台的基本概念以及它們如何協同工作來支持應用程式的後端。

LINE ChatBot 的運作原理:深入了解 LINE ChatBot 的架構和 API,以及如何與用戶進行互動。

第二部分:動手實作

設置 Firebase 環境:實際操作,建立 Firebase 專案並配置所需的服務。

開發 Cloud Function:學習如何編寫和部署 Cloud Function 來處理 ChatBot 的邏輯和資料存取。

整合 Gemini Pro Vision API:探索如何使用 Gemini Pro Vision 的 API 進行影像識別,並將其應用於收據管理。

第三部分:ChatBot 功能開發

旅遊資訊查詢:實現一個功能,讓用戶可以透過 ChatBot 查詢旅遊相關資訊。

收據上傳與識別:開發一個系統,讓用戶能夠上傳收據圖片,並利用 Gemini Pro Vision 的技術自動識別和整理收據資訊。

第四部分:部署與監控

ChatBot 的部署:學習如何將 ChatBot 部署到生產環境中,讓真實用戶開始使用。

監控與維護:介紹如何監控 ChatBot 的運行狀況,並進行必要的維護。

學員自備裝置

1.可連接網路筆電

2.Google Cloud 帳號

3.LINE 帳號

學員基礎能力需求

Python

Cloud Deployment

事前準備:

  • LINE Developer Account: 你只需要有 LINE 帳號就可以申請開發者帳號。
  • Google Cloud Functions: Python 程式碼的部署平台,生成供 LINEBot 使用的 webhook address。
  • Firebase:建立Realtime database,LINE Bot 可以記得你之前的對話,甚至可以回答許多有趣的問題。
  • Google AI Studio:可以透過這裡取得 Gemini Key 。

關於 Gemini API Price

根據官方網站: https://ai.google.dev/pricing?hl=zh-tw

image-20240410164827279

申請 Gemini API Key

  • 到 Google AI Studio https://aistudio.google.com/
  • Click “Get API Key”
  • 選擇你已經有綁定信用卡的付費帳號,來取得 API Keyimage-20240412195805278

申請一個 LINE 聊天機器人 (Messaging API)

image-20240410165008871

  • LINE Developer Console )並且登入 image-20240410165104899
  • 在挑選 Channel 的時候,如果要申請 LINE Chatbot (官方帳號),就要申請 Messaging API image-20240410170120876
  • 相關資料填寫上:
    • Cmpany or owner’s country or region:
    • Channel Name: 也就是你的 LINE Bot 名稱。
    • Channel description: 相關敘述來描述你 LINE Bot 做什麼。
    • 其他都可以隨便填寫即可。
  • 接下來要到 Messaging API Tab 執行以下設定:
    • Auto-reply messages: 關閉它 image-20240410170924360
  • 接下來要取得兩個重要的參數:
    • Basic Setting Tab 下方的 Channel secret image-20240410171544805
    • Messaging API Tab 下方的 Channel access token (long-lived) image-20240410171731815
  • 目前先到這邊,稍後還會回來設定相關 Webhook 。

建立一個 Cloud Run 服務

image-20240702213018935

  • 選擇好 Source Repository (應該是你自己的名字)

image-20240702213127188

  • 透過 Dockerfile 來啟動

image-20240702213157101

  • 機器設定可以挑選任何區域,但是 Authentication 要挑選 Allow unauthenticated invocations

Google Chrome 2024-07-02 21.32.25

  • Container(s), Volumes, Networking, Security 相關設定,需要將環境參數寫進去。
    • ChannelSecret: Your LINE channel secret.
    • ChannelAccessToken: Your LINE channel access token.
    • GEMINI_API_KEY: Your Gemini API key for AI processing.

image-20240703010240455

第一階段成果 - Gemini Pro 小幫手

image

第二階段: 讓我們來加上 Firebase Realtime Database

申請 Firebase Database 服務

  • 記得到 Firebase Console,直接選取你現在有的專案。(可能叫做 My First Project?)

  • 建立一個 Firebase Realtime Database 等等會用到

    image-20240413212830827

  • 地區選美國

    image-20240413212903957

  • Start in “lock mode”

    img

  • 為了開發方便,到 “Rules”設定成可以寫跟讀取,千萬注意:

    • 這是為了測試,請勿用在對外環境
    • 這是為了測試,請勿用在對外環境
    • 這是為了測試,請勿用在對外環境

image-20240413213202354

  • 記住哪個 URL (注意!之後要正式上線,需要改回權限),並且加上一個項目: “BwAI

image-20240413213802313

建立一個 Cloud Run 服務

image-20240702213018935

  • 選擇好 Source Repository (應該是你自己的名字)

image-20240702213127188

  • 透過 Dockerfile 來啟動

image-20240702213157101

  • 機器設定可以挑選任何區域,但是 Authentication 要挑選 Allow unauthenticated invocations

Google Chrome 2024-07-02 21.32.25

  • Container(s), Volumes, Networking, Security 相關設定,需要將環境參數寫進去。
    • ChannelSecret: Your LINE channel secret.
    • ChannelAccessToken: Your LINE channel access token.
    • GEMINI_API_KEY: Your Gemini API key for AI processing.
    • FIREBASE_URL: Your Firebase database URL.

image-20240702213433321

LINE Bot 完成最後設定

  • 到 “Messaging API” Tab
  • 填入 “Webhook URL” 數值,將剛剛得「觸發網址填上去」
  • 更新(update)後,使用 “Verify” 看看有沒有設定錯誤。
  • 如果沒有問題,可以打開「Use webhook」

image-20240412214745544

需要注意事項:

1. 發生 Error “Cloud Build trigger creation failed. Required role roles/iam.service/run.admin, roles/iam.services/iam.serciceAccloutUser”

image-20240703134145163

第一次建立 Google Cloud 專案之後,如果馬上使用 Cloud Run 就會發生這樣的錯誤。 主要是因為預設的 Compute Engine default service account 的權限不足。 修改方式如下:

  • IAM 的設定畫面
  • 修改 Compute Engine default service account 權限
  • 確定增加兩個權限
    • Cloud Run Admin
    • Service Account User

參考以下圖片:

Google Chrome 2024-07-03 13.51.05

2. 要注意一下 Cloud Function / Cloud Run Instance 開的伺服器夠不夠大

  • 如果 Firebase 資料放太多,要小心記憶體可能會不夠。記得 Cloud Function (Cloud Run) 記憶體要開得夠大。
  • 有使用到圖像處理,因為要把圖像整個讀取到記憶體中。也會有相關的考量。

3. 記得定期清理 Artifact Registry 空間 - 透過 Artifact Registry 直接設定 House Keeping 策略

  • Artifact Registry

    image-20240502234018634

  • 點選 size 最大的吧,然後選取上方 Edit Repository

  • 在最下方,選曲 Cleanup Policies

  • 選擇 “Keep most Recent versions”

  • “Keep count” 選 1 (也可以是 2)

image-20240502234314012

如果怕刪除太多,可以用 Dry run 看看結果。

完整原始碼

你可以在這裡找到相關的開源程式碼:

衍伸應用

透過 Cloud Run / Cloud Function 可以很快速部署服務到 Google Cloud 並且很快的讓你的 LINE Bot 可以上線。以下有相關應用可以去參考一下: