iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
自我挑戰組

從零開始的AI學習之路:非本科轉職的30天挑戰記系列 第 24

D24 | 我的Side Project 每拍呷--資料庫篇

  • 分享至 

  • xImage
  •  

今日進度:10/14
研究資料庫怎麼使用,主要使用Firestore,並將LINE BOT的用戶資訊存進去


首先讀官方文件,先做出程式碼測試看看,可以成功存users的資料💯

# 要先安裝: pip install --upgrade firebase-admin
# 初始化
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore

# Use a service account.
cred = credentials.Certificate(r"XXXXX.json") # 金鑰的路徑
app = firebase_admin.initialize_app(cred)
db = firestore.client()

# 建立 users 集合
doc_ref = db.collection("users").document("alovelace")
doc_ref.set({"first": "Ada", "last": "Lovelace", "born": 1815})

doc_ref = db.collection("users").document("aturing")
doc_ref.set({"first": "Alan", "middle": "Mathison", "last": "Turing", "born": 1912})

# 讀取資料
users_ref = db.collection("users")
docs = users_ref.stream()

for doc in docs:
    print(f"{doc.id} => {doc.to_dict()}")

可以看到Firestore已經有兩筆users的資料

https://ithelp.ithome.com.tw/upload/images/20250829/20177974WQJThyHmsA.png

由於 LINE Bot 的 API 回應是無狀態的 (stateless),每次使用者傳送訊息,對話都是從頭開始。為了解決這個問題,需要用 Firestore 來儲存使用者的「對話狀態」,以便 Bot 知道接下來要問什麼。
在 Firestore users 集合中,除了 height 和 weight 欄位,還需要新增一個 state 欄位來記錄對話進度。

例如:
state: 0:初始狀態,Bot 應該詢問身高。
state: 1:已詢問身高,等待使用者輸入身高。
state: 2:已輸入身高,Bot 應該詢問體重。

我的測試流程是--
用戶輸入您好觸發對話:

用戶:您好
BOT:請輸入身高
用戶:158
BOT:請輸入體重
用戶:60
BOT:記錄完畢。

然後我去Firestore可以看到這個用戶的資料是{height: 158, weight: 60}

不過,遇到一個小問題如下:

用戶:您好
BOT:您好,請輸入您的身高(例如:170)
用戶:158
BOT:請輸入您的身高(例如:170)
用戶:158
BOT:請輸入您的體重(例如:65)
用戶:58
BOT:紀錄完畢,謝謝您!

BOT問了用戶兩次身高,重複詢問了;
這是因為程式碼在處理「新用戶」的邏輯時,與後續的狀態處理邏輯產生了衝突。
當新用戶傳送「您好」時:
程式碼進入 if not doc.exists: 這個區塊,因為 Firestore 中還沒有這個用戶的資料。

它會設定 state 為 0,並回覆 您好,請輸入您的身高(例如:170)。
接著,return 會結束這次的函數執行,程式沒有繼續往下走。

當用戶接著輸入 158 時,程式會再次執行。
這次 doc.exists 是 True,所以不會進入「新用戶」的區塊。
程式碼來到 current_state = user_data.get('state', 0)。
此時,state 的值是 0(因為上一個步驟剛設定)。
程式碼接著進入 if current_state == 0: 這個區塊。
它再次回覆 請輸入您的身高(例如:170),並將 state 更新為 1。
這就是 Bot 問了兩次身高的原因,故需要修改邏輯,讓新用戶在第一次發送訊息時,直接把狀態設定為1,並發送第一次的詢問訊息。這樣,當用戶第二次發送訊息(身高)時,程式碼就不會再進入 state == 0 的區塊。
解決!


再來第二個測試,我想測BMI:從資料庫裡面拿取剛剛存的資料作運算返回一個值給用戶。

例如,用戶傳給LINE BOT:我要BMI,後台就去資料庫拿這位用戶的體重跟身高,然後用程式碼裡寫好的BMI公式,算到四捨五入到小數點後一位傳給用戶:

用戶:我要BMI
BOT:好的,您的BMI是26.2

https://ithelp.ithome.com.tw/upload/images/20250829/20177974gZpSd1ifDv.png

因為之後要把原本主程式碼跟Firestore整合,還有OCR辨識要改成能否有Gemini API,
所以這邊先測試看看能否上傳照片讓Gemini辨識營養成分後計算出攝取完一包獲得的熱量。

例如:用戶上傳一張營養標示,假設Gemini辨認出一包200公克的餅乾,一份是10公克、本包裝含20份,每份熱量是50卡、每份的糖是5克,所以吃完一包會是50卡X20份=1000卡,糖是5克X20份=100克糖;用戶若是158公分、60公斤,BOT就回傳給他:
您好,您的BMI是24,吃完一包熱量為1000卡,攝取了100克的糖。

幾乎等於是要大改了,明天繼續努力!


上一篇
D23 | 我的Side Project每拍呷--檢討改善篇
下一篇
D25 | 我的Side Project 每拍呷--美化篇
系列文
從零開始的AI學習之路:非本科轉職的30天挑戰記30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言