跳轉到內容
全部文章

一次 AI 請求只是開始。

跟隨一個任務穿過授權、持久執行、用量追蹤,直到使用者可以回訪的結果。

supastack 團隊約 4 分鐘閱讀

How should I build AI features in a SaaS?

It depends on whose keys, whose data, and whose budget. Let users or workspaces bring their own provider keys if cost and privacy matter, encrypt those keys at rest, and route requests through one boundary that records usage. Decide upfront whether execution is synchronous or a background job, and name the failure modes: timeouts, rate limits, malformed output, and partial results. Tie spend to a per-workspace budget and show usage. supastack provides a provider router, encrypted BYOK storage, budgets, and background jobs, but the product decisions about data and limits remain yours.

在模型執行之前

使用者提供提示詞和一個別名,如 cheap、fast 或 smart。生產服務端在接受任務之前檢查認證、工作區歸屬與許可權。供應商模型 ID 與金鑰留在這條邊界之後——友好的別名是客戶端唯一需要的模型詞彙,因為到真實供應商模型的對映是配置,而不是契約。

持久的任務記錄在後臺執行開始前就給請求一個身份。這個身份把提交、worker、用量記錄與結果串起來,也讓使用者在離開頁面後能找回這項工作。

順序很重要:昂貴的工作只在便宜的檢查通過之後才開始。在任何任務入隊之前先驗證認證、歸屬與許可權,能讓未認證或未付費的請求永遠到不了供應商——也讓失敗對使用者可解釋。AI 模組指南記錄了這些檢查住在哪裡;工作區邊界一文解釋了為什麼歸屬在服務端推導,而不是信任客戶端。

決定用誰的金鑰、誰的上限

AI 功能是一個花錢的決定。supastack 允許工作區自帶供應商金鑰——加密儲存、絕不暴露給客戶端——或跑在平臺金鑰上,並按模型價格目錄執行每個工作區的預算。無論你怎麼實現,問題都一樣:誰付錢,上限在哪裡執行?

執行屬於服務端工作流,而不是瀏覽器側的估算。生成之後才檢查的預算只是記錄超支;派發之前檢查才能阻止超支。供應商金鑰設定講了配置那一側。

讓執行顯式化

Trigger.dev 執行 ai.generate 工作流。能力感知路由器根據已配置策略與請求要求選擇模型。把該策略當作運維輸入:不可用的別名不應在介面上顯示為可用選項。

提交過程中的網路故障會讓客戶端不確定任務是否已入隊。生產路徑使用任務級冪等鍵與已儲存的提交,使恢復可以複用原始請求。每次超時後都新建任務,會有重複工作與重複扣費的風險。

永續性也是讓介面保持簡單的東西:介面讀取任務狀態並渲染,而不是編排重試。當生成跨模型呼叫、工具步驟或排程時,顯式的工作流契約——enqueue、status、cancel——才是讓“進行中”保持誠實的機制。

給失敗模式點名

在請求與結果之間,會出錯的是一個具體而有限的集合。按名字逐個設計,而不是為籠統的“錯誤”設計——每個任務都應該落到可解釋的狀態:已入隊、執行中、帶原因的失敗、或帶結果的完成。任務恢復是套件在恢復一側的參考。

底下對介面的要求是:任何狀態都不能撒謊。比工作活得更久的轉圈,或是為從未執行的任務亮出的成功訊息,都是一張等著發生的客服工單和計費糾紛。

  • 提交超時——通過已儲存的提交與任務級冪等鍵恢復,而不是重新入隊。
  • 供應商在任務中途失敗——把任務標記為失敗,並給出介面能展示的原因。
  • 預算耗盡——在派發之前拒絕,而不是在花完之後。
  • 使用者離開了頁面——持久記錄與恢復 URL 能找回狀態和結果。

追蹤發生了什麼

生成產生的不只是文本。應用會記錄用量與任務結果,介面通過已認證的 API 讀取狀態。正是用量記錄讓預算可以執行——它在結果返回之前寫入,而不是事後估算。

完成郵件是獨立的步驟,有獨立的投遞記錄。模型響應成功並不能證明郵件已送達。把這些結果分開,讓失敗更容易解釋與重試,而不必無謂地重跑模型。

結果還需要一個使用者可以回訪的家:任務頁、歷史列表、或隨完成郵件送達的恢復 URL。只存在於轉瞬即逝的通知裡的生成,是你遲早被要求再做一遍的工作。

驗證每一條邊界

先用確定性的 fake 介面卡測試應用的決策:拒絕訪問、停用別名、重複提交、結果恢復與通用錯誤。這些測試應在沒有供應商憑證的情況下執行。

然後使用明確 opt-in 的供應商冒煙流程驗證真實整合。它要求檔案化的沙箱配置以及對外呼叫的批准。這種區分讓日常開發保持快速,也讓生產證據具體且可追溯。

產品變化時保持這種劃分穩定:在每個邊界決定附近都有確定性覆蓋,這樣換供應商、改路由策略或新增別名只會讓測試失敗,而不是讓客戶失敗。

關於 SaaS 中 AI 功能的常見問題

每次談到把 AI 放到付費牆後面,總會冒出這幾個問題。

  • AI 功能的授權應該放在哪裡? —— 在任何任務入隊之前:認證、解析工作區、檢查權益,然後才建立任務。生成之後才跑的檢查只是在給濫用做記錄。
  • 我需要支援 BYOK 嗎? —— 如果你的客戶有自己的供應商關係,就需要:它決定誰付錢、誰擁有速率上限。金鑰要加密儲存、遠離客戶端——AI 配置指南講了這個模型。
  • 怎麼防止重試造成重複計費? —— 把冪等鍵限定在任務上,並在恢復時複用已儲存的提交,這樣一次超時就造不出第二次計費執行。
  • 應該記錄哪些用量資料? —— 按任務記錄:模型、消耗的單位、對照價格目錄算出的成本,以及所屬工作區——足夠執行預算、也足夠回答支出問題,而無需重跑任務。
  • 什麼時候生成該放進後臺任務? —— 只要它可能比一次請求活得久。模型延遲、重試和多步工作都要求持久執行;只有即時且便宜的呼叫才適合內聯。

常見問題

14 個問題

supastack 是什麼?

supastack 是用於構建 AI 驅動 SaaS 產品的模組化基礎。它把通用基礎設施整合在一起,讓你專注於產品專屬的功能。

它支援 Web 和移動端嗎?

支援。supastack 包含 Next.js 與 Expo 應用,作為 Web 與移動端體驗的起點。

包含哪些認證方式?

Better Auth 覆蓋郵箱/密碼、OTP 與社交登入。個人工作區隨賬戶一起開通,產品記錄從第一天起就有邊界。

AI 是如何支援的?

supastack 包含可配置的多供應商 AI、用量追蹤、預算,以及加密的自帶金鑰(BYOK)支援。

訂閱如何處理?

對於基於該套件構建的產品,Stripe 計費、訂閱與許可權構成付費訪問的基礎。供應商金鑰僅存於服務端。

我的產品專屬程式碼放在哪裡?

產品專屬功能保留在獨立的程式碼庫中,產品通過配置接入 supastack 的基礎模組。

supastack 如何定價?

套件為一次性購買、終身更新:單棧 249 美元(Next.js(Web)、Expo(iOS 與 Android)、Tauri(macOS 與 Windows 桌面)倉庫任選其一),雙棧 398 美元(任選兩個倉庫),或完整套裝 399 美元(全部三個倉庫與完整 monorepo),每個額外開發者席位 75 美元。套件本身沒有訂閱。本站結賬後通過郵件傳送許可證金鑰,倉庫訪問通過 GitHub 邀請授予。

工作區如何界定我的資料?

使用者記錄按 workspaceId 劃定邊界。身份、許可權、AI 用量、計費事件與審計條目都留在個人工作區邊界內。

後臺任務如何工作?

Trigger.dev 是明確的任務執行時。JobRunner 契約只承諾 enqueue、status 與 cancel——工作流語義保持 Trigger.dev 專有且顯式。

郵件與營銷觸達有何不同?

事務性郵件覆蓋產品工作流,如任務完成通知。冷觸達與營銷活動屬於產品自身的範疇,不在本套件的郵件模組內。

移動端購買如何運作?

移動端已支援 RevenueCat 原生購買和恢復購買,訪問許可權由服務端驗證。釋出前需配置商店賬戶並完成裝置測試。Web 計費保持獨立。

AI 供應商金鑰存放在哪裡?

自帶金鑰憑證經過加密且僅存於服務端。金鑰在日誌中被脫敏;用量與預算在工作區級別保持可見。

結賬支援哪些付款方式?

Stripe 託管結賬接受銀行卡,在 Stripe 賬戶啟用後還可提供支付寶與微信支付——方便中國買家。錢包授權為非同步確認,付款完成後許可證頁面會立即更新。

我能申請退款嗎?

獲得程式碼倉庫訪問許可權後,supastack 將永久歸你所有,因此無法退款。但請放心,你將獲得包含終身更新的完整原始碼,可為你自己或客戶構建併發布無限數量的產品。你只需注意不能轉賣程式碼,也不能將倉庫作為啟動模板二次分發。唯一的例外是上線返現——上線一款用 supastack 打造的真實產品並公開分享,在購買後 60 天內達到 5,000 次自然瀏覽或 50 個自然按讚,即可退還已付款項的 50%;詳見條款。

TW