歡迎來到最後一天!照過往參賽的邏輯,今天都會是一個反省與回顧的好日子,我個人的回顧比較沒人在乎,會放在文章結束前,我們主要還是先回顧一下這30天來我們究竟做了些什麼,這些學到的東西是否真的足夠你打造屬於你自己的 AI 應用程式,又或是回過頭來我發現自己是標題詐欺,馬上就開始吧!
✅ 專案成果總覽:盤點 AI 面試官最終實現的核心功能。
✅ 核心架構圖:用一張流程圖,清晰地展示整個系統的運作模式。
✅ AI 應用開發思路:將我們的經驗,整理成一套可參考的開發步驟。
✅ 未來展望:探討這個專案還能往哪些方向進化與升級。
經過 30 天的迭代,我們的專案已經從一個簡單的 API 呼叫器,成長為一個功能完備的迷你全端應用:
👨💻 使用者認證系統:整合 Supabase Auth,實現了完整的註冊、登入、登出流程。
🏠 現代化主頁面:一個還算美觀的專案首頁。
💡 三種評測模式:
如果要把我們整個專案後端最核心的 /api/interview/evaluate
路由的運作邏輯視覺化,它會是下面這張圖。這張圖清晰地展示了系統如何根據不同的題目類型,選擇不同的「專家路徑」來準備上下文,最後再統一交給 Gemini AI 進行總評。
graph TD
subgraph Frontend
A[使用者在瀏覽器提交答案]
end
subgraph "Next.js API Route (/api/interview/evaluate)"
A --> B{接收請求並驗證使用者};
B --> C{判斷題目類型};
C -- 概念題 (concept) --> D[1.RAG 流程];
D --> D1[生成答案 Embedding];
D1 --> D2[在 Supabase中<br>進行語意相似度搜尋];
D2 --> D3[取得相關的 keyPoints];
D3 --> E[準備 RAG Context];
C -- 演算法題 (JS code) --> F[2.Judge0 流程];
F --> F1[將程式碼送往 Judge0 API];
F1 --> F2[在安全的沙箱容器中執行];
F2 --> F3[取得 stdout / stderr 結果];
F3 --> G[準備 Judge0 Result];
C -- 前端框架題 (React code) --> H[3.原生 SSR 評測流程];
H --> H1[使用 Babel 即時轉譯 JSX];
H1 --> H2[使用 React SSR <br>將元件渲染成 HTML 字串];
H2 --> H3[比對 HTML 與預期結果];
H3 --> G;
E --> I[buildUnifiedPrompt];
G --> I[buildUnifiedPrompt];
I --> J[組合最終的 Prompt];
J --> K[呼叫 Gemini API<br>];
K --> L[將 AI 回應以串流形式<br>回傳給前端];
K --> M((非同步))
end
subgraph Database
M -.-> N[將評估結果<br>寫入 practice_records];
end
style A fill:#D6EAF8,stroke:#3498DB
style L fill:#D6EAF8,stroke:#3498DB
style N fill:#D5F5E3,stroke:#2ECC71
雖然這個系列文在 AI 面試官 的種種功能花了許多篇幅描述,也走了很多歪路,但就像我第一天說過了,這個專案本身只是一個例子,透過這個系列文,我更想分享的是一套思考框架:「到底該怎麼打造現在常見的 AI 應用?」,經過這樣的實際開發流程與資料研究,我想我比一個月前的自己更有信心能回答這個問題了,大致上應該會分成以下幾個步驟:
這是所有 AI 應用的起點。在這個階段,我們只做最簡單的一件事:建立一個 Input -> LLM -> Output 的基礎流程。
這是讓你的 AI 應用從「普通」變「好用」的關鍵。通用 AI 的能力大家都能用,但你提供的專業資料,才是你專案價值的來源。
keyPoints
知識庫。當評估使用者答案時,我們不再讓 AI 憑空想像,而是先透過語意搜尋,找出最相關的 keyPoints
,然後告訴 AI:「請參考這些重點,來給出你的評價。」有時候,光有知識還不夠,AI 需要有能力與外部世界互動或取得即時數據。這就是為 AI 接上「工具」的意義,在行業中這通常被稱為「工具使用 (Tool Use)」或「函式呼叫 (Function Calling)」,這也是目前常見的 AI Agents 以及 各大 LLM 在頁面中開始推行的功能,舉凡讓 AI 能在對話中產生圖像、影片甚至是替你寄信都屬於這個範疇,簡單來講就是讓 AI 有能力使用對話之外的工具協助你達到你的成果。
不過特別要注意一下,在我們專案中的例子我們是由開發者去調用工具再將結果交給 AI,嚴格說起來我們這樣不算是 Function Calling ,我們只是透過工具去提供 AI 更有意義的 Context 協助產生更高品質的回覆,而並不是像 AI Agents 一樣自行判斷什麼時候該呼叫 Function Calling(通常是透過關鍵字或是語意化判斷),在我們專案中並沒有這類的需求去串接不同的 MCP Server,因此這部分實際上在我們專案中暫時沒有更好的例子可以做說明。
這三個步驟處理完後,你就得到了一個強大的「AI 核心」。剩下的使用者系統、資料庫、UI/UX 優化等,都是將這個核心包裝成一個完整產品所必需的、相對常規的軟體開發工作。
這個專案目前其實還相當陽春,這部分我要負擔全責,原本照我的計劃它應該要遠比現在完整,過程中的一些意外與私人行程確實大大打亂了我的步調,再次證明一件事情:「你永遠不該裸賽鐵人賽」。
這類的專案如果還要再繼續拓展,大致上可以分為幾個前進的方向:
child_process
搭配 Node.js Permission Model,甚至挑戰 Docker 容器化做出獨立的沙盒環境,讓前端程式碼實作測驗題目可以真正上線終於結束了,每次參加鐵人賽我的套路都是一樣的,早早有報名的心理準備 -> 拖到最後一天開賽 -> 手上一篇存稿都沒 -> 完賽後再發誓下次參加絕不裸賽。 這麼看來我在這方面可真是一點成長都沒有,這一次的專案也是一時興起就圓了一個拖很久的夢想,又加上 AI 的話題避也避不開,萌生了將這兩個靈感結合的想法,最終產出了這個專案,要反省的事情隨便列都一大堆,但我認為最嚴重的莫過於「完全沒先做 POC 就規劃使用大量沒碰過的東西整合專案。」過程中的研究與實驗花了大量的時間,即便在三個 AI 服務的支援下還是相當費時(尤其是較新的服務 API 串接真的是有夠悲劇,沒一個有用),為了彌補花費的時間不得不多了許多的緩衝日去修正之前的錯誤,成品因此沒有了預期的完整度。
但整個過程我還是覺得相當有收穫,雖然讀 LLM 論文的那幾天讓我回憶起了痛苦的碩班生涯,但後續的處理語意向量化以及整合都讓我感到相當興奮,審視專案架構時讓我發現當初規劃時的草率,也藉由大量的 AI 協作優化了我自己的工作流程,這些都是很有趣的經驗,雖然基本上佔掉了我大量的下班時間,不過說實在把時間花在看動漫瘋或打Xbox不見得比較有趣,我還是挺喜歡寫程式的。
這三十天來辛苦了,希望這一系列的文章多少讓你有一點點收穫,在之前的文章我東漏西漏了不少,如果你真的有跟著文章做發現跑不動,那肯定是我的問題,再麻煩你留言給我,我會盡量撥空與你一同解決!那麼再會啦!Cheers!