Some checks failed
CD Pipeline / deploy (push) Failing after 59s
- 建立 Gitea Actions CD pipeline (.gitea/workflows/cd.yaml) - 部署模式: rsync Python 檔案至 188 → docker restart (volume mount) - Dockerfile/requirements 變動時自動重建 Docker image - 部署通知: Telegram (開始/成功/失敗) - 健康檢查: https://mo.wooo.work/health (最多 5 次重試) - 同步最新 CLAUDE.md / ADR-008 / memory (2026-04-19) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
89 lines
2.9 KiB
Markdown
89 lines
2.9 KiB
Markdown
# ADR-004:NemoTron 配額耗盡 fallback 至 Hermes Rule-based
|
||
|
||
- **Status**: Accepted
|
||
- **Date**: 2026-04-18
|
||
- **Decision Maker**: 統帥(顧問補充建議第 2 條)
|
||
- **Author**: Claude
|
||
|
||
## Context
|
||
|
||
NemoTron 走 NVIDIA NIM,每日 80 次免費配額(保留 20 給 AWOOOI,實際可用 60 次)。風險場景:
|
||
- **雙 11 / 母親節 / 聖誕** 等大促時,告警暴增可能瞬間耗盡配額
|
||
- **PChome 突發降價戰** 觸發大量競價威脅分類
|
||
- **任何單日異常** 導致 webhook 大量被觸發
|
||
|
||
一旦 NemoTron 回 HTTP 429(Too Many Requests),現有代碼會直接報錯 → 告警靜默 → 業務風險。
|
||
|
||
## Decision
|
||
|
||
**NemoTron 必須有兩階 fallback 鏈**:
|
||
|
||
```
|
||
告警觸發
|
||
│
|
||
▼
|
||
NemoTron (NIM) ─── HTTP 200 ─→ 正常派發
|
||
│
|
||
└─ HTTP 429 / timeout / network error
|
||
│
|
||
▼
|
||
Hermes (Ollama 本地) Rule-based 派發
|
||
│
|
||
├─ 已知告警類型 → 對應 template 派發 Telegram
|
||
└─ 未知類型 → 兜底 template + 標記「降級模式」
|
||
```
|
||
|
||
**降級模式特徵**:
|
||
- 派發訊息開頭加 `🟡 降級派發` 標記
|
||
- 不嘗試做複雜決策(不調用 store_insight 等需要 reasoning 的 tool)
|
||
- 純 if-else 分類 + template 渲染
|
||
|
||
## Alternatives Considered
|
||
|
||
| 方案 | 拒絕原因 |
|
||
|---|---|
|
||
| 直接 fallback 到 OpenClaw/Gemini | 大促時 OpenClaw 配額也很緊張;付費成本暴增 |
|
||
| 進入告警佇列等配額恢復 | 告警時效性最重要,等不起 |
|
||
| 不做 fallback,直接 alert 統帥 | 告警靜默風險巨大 |
|
||
|
||
## Consequences
|
||
|
||
### Positive
|
||
- 告警永不中斷(即使 NemoTron 全掛)
|
||
- 大促日成本依然受控(不會意外切到 OpenClaw 燒錢)
|
||
- Hermes 本地 = 永遠可用兜底
|
||
|
||
### Negative / Trade-offs
|
||
- 降級期間決策品質下降(rule-based 不如 LLM)
|
||
- 需要維護一套 rule template(增加代碼量)
|
||
- Hermes 主機壓力會在降級時激增
|
||
|
||
## Implementation Notes
|
||
|
||
```python
|
||
# services/nemotron_dispatcher_service.py
|
||
class DispatchResult:
|
||
mode: Literal['normal', 'degraded']
|
||
text: str
|
||
|
||
def dispatch_alert(alert: Alert) -> DispatchResult:
|
||
try:
|
||
return _nemotron_dispatch(alert) # NIM tool calling
|
||
except (RateLimitError, TimeoutError, RequestException) as e:
|
||
sys_log.warning(f"[NemoTron] degraded: {e}")
|
||
return _hermes_rule_fallback(alert)
|
||
|
||
def _hermes_rule_fallback(alert: Alert) -> DispatchResult:
|
||
template = RULE_TEMPLATES.get(alert.type, RULE_TEMPLATES['default'])
|
||
text = template.render(alert=alert)
|
||
return DispatchResult(mode='degraded', text=f"🟡 降級派發\n{text}")
|
||
```
|
||
|
||
監控加上:
|
||
- Prometheus metric: `nemotron_fallback_total` counter
|
||
- Grafana 告警:5 分鐘內 fallback > 10 次 → 通知統帥(系統級異常)
|
||
|
||
## Related ADRs
|
||
|
||
- ADR-001:三 Agent 分工(NemoTron 處理層、Hermes 採集層)
|