「在 AI Agent 系統中,對外連線的大模型 API 門戶是系統中最脆弱的一環。一個 Production-Ready 的 Gemini API Gateway,必須具備精準的滑動視窗限流、佇列管理、每日 Quota 自動重置,以及結構化的金融專家 Prompt 注入,才能打造出不可摧毀的服務韌性。」
先前,我們解剖了 FastAPI 主服務、對話記憶模組、自主學習模組與 RAG 向量引擎。今天我們將深入 Angelina AI Agent 的大模型對外心臟——gemini_gateway.py。
作為封裝 Google Gemini 2.5 Flash API 的核心元件,GeminiGateway 不僅負責 HTTP 連線與 Payload 組合,更肩負著 Rate Limiting、Quota Management 與系統 Prompt 注入的關鍵重任。
今天我們將解析 gemini_gateway.py 的客製化 Exception 體系、限流佇列演算法與金融專家 Prompt 裝配流程!
為了能針對不同的 API 異常情境做出最精準的 HTTP 響應,gemini_gateway.py 建立了一套清晰的 Exception 繼承體系:
1. 核心 Exception 類別定義
(1) GeminiError:全域基底例外類別,包覆 message 與 status_code。
(2) GeminiAPIError:當 Gemini 回傳一般 4xx/5xx 錯誤時拋出,對應 HTTP 502 Bad Gateway。
(3) GeminiTimeoutError:當請求超過 30 秒 (_REQUEST_TIMEOUT_SECONDS = 30.0) 時拋出,對應 HTTP 504 Gateway Timeout。
(4) GeminiQuotaExhaustedError:當 API 額度耗盡(429 且帶有 quota 或 RESOURCE_EXHAUSTED 關鍵字)時拋出,對應 HTTP 429 Too Many Requests。
(5) GeminiQueueFullError:當待處理請求佇列超過容量時拋出(HTTP 429)。
2. UTC 午夜 Quota 自動重置
當觸發 Quota 耗盡時,Gateway 會紀錄當前的 UTC 日期(YYYY-MM-DD)。在後續的每一次請求前,quota_exhausted 屬性會自動比對當前 UTC 時間:
# gemini_gateway.py 中的 UTC 午夜自動重置邏輯
@property
def quota_exhausted(self) -> bool:
if self._quota_exhausted:
today_utc = datetime.now(timezone.utc).strftime("%Y-%m-%d")
if self._quota_exhausted_date != today_utc:
# 跨越 UTC 午夜,自動清除熔斷標記!
self._quota_exhausted = False
self._quota_exhausted_date = None
logger.info("gemini_quota_reset", message="Quota auto-cleared at UTC midnight.")
return self._quota_exhausted
免費階層 API 最怕瞬間併發流量導致服務被硬性封鎖。GeminiGateway 在內部實作了嚴密的限流護欄:
1. 流量控制參數
(1) _MAX_REQUESTS_PER_MINUTE = 15:每分鐘最多允許 15 次請求(15 RPM)。
(2) _QUEUE_CAPACITY = 10:最多允許 10 筆請求在佇列中排隊等待。
2. 滑動視窗與佇列機制
(1) 透過 asyncio.Lock 保護 _request_timestamps 時間戳記陣列,自動清理過期(超過 60 秒)的紀錄。
(2) 即時放行:若近 60 秒內的請求次數 $< 15$,立即放行並紀錄時間戳。
(3) 容量排隊:若已達 15 次,檢查當前佇列計數(_queued_count)。若未達 10 筆上限,計算預估等待時間(ceil(queued_count / max_rpm))並進行 await asyncio.sleep(wait_time) 避讓。
(4) 佇列熔斷:若排隊計數 $\ge 10$,直接拋出 GeminiQueueFullError 快速拒絕,防止服務記憶體因爆量請求而崩潰。
每一次發送給 Gemini 的 Payload,都會由 _build_payload() 進行多層次注入,確保 Agent 的回答始終保持最高專業度:
1. 語言與角色硬性規定
(1) 多語言切換:zh-TW 自動注入「You MUST respond in Traditional Chinese (繁體中文)」,其餘語言注入英文指示。
(2) 來源標籤規則:強制規範引用知識庫時必須明確標註「來源: NotebookLM 筆記本」或「來源: 對話學習」。
(3) 風險免責聲明:若使用者問題涉及投資風險,強制附加「本建議僅供參考,實際投資決策請諮詢持牌理財顧問。」警語。
(4) 非金融話題拒絕:非金融相關問題禮貌拒絕並引導重新發問;超出一知半解範疇時嚴禁捏造。
2. Context 與 Knowledge Chunks 組合
Payload 的 contents 陣列會依序包裝:
(1) RAG 參考知識:若有 knowledge_chunks,包裝為 [Knowledge Source - type]: text 作為對話前導。
(2) 對話歷史 (context_turns):對齊 user 與 model 角色將近 20 輪歷史紀錄寫入。
(3) 當前對話:寫入使用者最新傳入的 user_message。
透過 app/services/gemini_gateway.py 的程式碼解析,我們確認了:
1. 極致的連線韌性:30 秒 Timeout 捕捉、UTC 午夜 Quota 自動重置,以及 15 RPM / 10 佇列限流,徹底告別 API 崩潰。
2. 高專業度回覆護欄:結構化 System Prompt 注入,完美控管了多語言、來源標註、免責聲明與防幻覺規則。
明天(Day 30)我們將迎來本系列的終章~!