歡迎來到鐵人賽 Day 2!昨天向大家說明了這個APP的誕生,也確立了用 AI 來拯救我們破碎課表的偉大目標。
但在真正實作之前,我們需要將需求確立清楚,才有辦法讓AI知道我們的需求跟限制是什麼,避免整個專案架構太過複雜、維護成本高。
所以,今天的任務就是畫出系統藍圖!這個架構並非靠本身一己之力,而是根據經驗人士的建議、AI的協作與一些個人的想法共同協作想出。
前端 (Mobile App) — React Native:
為了達到雙平台的目的(iOS/Android)而選擇,撰寫 React Native 可以讓我用一套 Code 同時產出 iOS 和 Android 版本,雖然對撰寫APP沒經驗的我是個痛點,但過去有使用過TypeScript的經驗,對於下班時間寶貴的我們來說,這是 CP 值最高的選擇。
後端 (Backend API) — Java:
為了不讓學習成本持續跌高,我選擇 Java,這也是過去比較常接觸到的語言,這語言強大的物件導向與豐富的生態系,非常適合來處理複雜的商業邏輯。
雲端運算 (Cloud Infra) — GCP
GCP我也是第一次使用,但平常經常接觸另一個雲端服務商 AWS(Amazon Web Service),因此學習成本沒有像 React Native 來得這麼高,能夠運用他服務的概念來實際運用,讓我非常期待!預計把 Java 打包成 Container 丟上 Cloud Run,一個全託管、Serverless 且自動擴展的服務,不僅不用自己管機器,還能根據需求控制預算。
AI 大腦 — Gemini API:
負責接收來自 Java 後端整理好的「使用者狀態(例如:今天又加班沒跑完)」,並進行推理,吐出全新的訓練課表。
資料庫 (Database) — Firestore:
GCP 提供的 Serverless NoSQL 資料庫,有提供免費額度。主要能讓後端 Java 整合,用來存 JSON 格式等格式。
簡易架構圖如下:
在藍圖確定後,我們今天先不急著把所有環境架好,而是要先定義「邊界」。我們在 Java 後端會先開出一個 API 介面(Controller),這就是未來手機端要來溝通的唯一入口。如下面範例:
@RestController
@RequestMapping("/api/v1/training")
@RequiredArgsConstructor
public class TrainingPlanController {
// 注入處理 AI 邏輯與資料庫的 Service
private final GeminiCoachService coachService;
@PostMapping("/adjust")
public ResponseEntity<AdjustPlanResponse> adjustPlan(@RequestBody AdjustPlanRequest request) {
// Controller 保持乾淨,只負責接收狀態,髒活累活全交給 Service
AdjustPlanResponse newPlan = coachService.generateAdjustedPlan(request);
return ResponseEntity.ok(newPlan);
}
}
這段 Controller 的骨架,確立了我們整個資料流的入口:
POST 路由。未來手機端不管發生什麼事(例如今天加班沒跑完),只要把使用者的最新狀態打包成 JSON 往這裡送就好。所謂的不讓前端直接跟AI聊天,不是指使用者在UI介面上不跟AI聊天,而是避免透過React Native開發的前端,直接呼叫Gemini API!!
為什麼還特地規劃成從後端呼叫Gemini API,而不是直接呼叫 Gemini API?!
今天我們攤開了 KAKERU 的系統藍圖,確認了 React Native、Java、Cloud Run、Firestore 與 Gemini API 各司其職的流程。個人的小原則:前端求穩、後端扛揍、AI 盡情發揮,然後預算要省!
既然藍圖畫好了,我們也要開始來了解雲端了。
不過問題來了:同樣是 GCP 上的無伺服器架構(Serverless),為什麼我會選擇Cloud Run而不是 Cloud Functions? 明天(Day 3) 會說明我的原因,也是藏著攸關錢包與效能的計費迷思!我們明天見!