feat: graceful degradation when FoJin API is unavailable (P0)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
xianren
2026-04-05 08:04:24 +08:00
parent da2a7f2dc8
commit 5688f40c1a
3 changed files with 37 additions and 5 deletions
+8
View File
@@ -36,3 +36,11 @@ python3 ${CLAUDE_SKILL_DIR}/tools/rag_query.py kg "<人物名>" --type person
4. 如果检索无结果,坦诚说明并基于 teaching.md 中的已有内容回答 4. 如果检索无结果,坦诚说明并基于 teaching.md 中的已有内容回答
5. 每次回答至少引用 1-2 段检索到的真实经文 5. 每次回答至少引用 1-2 段检索到的真实经文
6. 引用经文时标注出处,格式示例:《大般若经》卷一([FoJin链接](https://fojin.app/texts/123) 6. 引用经文时标注出处,格式示例:《大般若经》卷一([FoJin链接](https://fojin.app/texts/123)
## 降级处理
如果 rag_query.py 返回 "[FoJin API 当前不可用]" 消息:
1. 继续以该法师角色回答,但明确告知用户:"当前无法实时检索 FoJin,本次回答基于内置资料"
2. 仍然依据 teaching.md 和 voice.md 组织回答
3. 引用 teaching.md 中已有的经文链接(这些是预先验证过的)
4. 在回答末尾加上:"如需最新的 FoJin 检索结果,请稍后重试"
+17 -1
View File
@@ -7,12 +7,18 @@ Two modes:
""" """
import json import json
import logging
import os import os
from typing import Optional from typing import Optional
import requests import requests
class FojinUnavailableError(Exception):
"""Raised when FoJin API is unreachable. Callers should handle gracefully."""
pass
class FojinBridge: class FojinBridge:
"""Bridge to FoJin Buddhist text platform.""" """Bridge to FoJin Buddhist text platform."""
@@ -108,11 +114,21 @@ class FojinBridge:
# ── Helpers ────────────────────────────────────────────── # ── Helpers ──────────────────────────────────────────────
def _get(self, path: str, params: Optional[dict] = None) -> dict: def _get(self, path: str, params: Optional[dict] = None) -> dict:
"""Make GET request to FoJin API.""" """Make GET request to FoJin API.
Raises:
FojinUnavailableError: When FoJin is unreachable (connection/timeout)
requests.HTTPError: On 4xx/5xx responses
"""
url = f"{self.base_url}{path}" url = f"{self.base_url}{path}"
try:
resp = self.session.get(url, params=params, timeout=30) resp = self.session.get(url, params=params, timeout=30)
resp.raise_for_status() resp.raise_for_status()
return resp.json() return resp.json()
except requests.ConnectionError as e:
raise FojinUnavailableError(f"FoJin API unreachable: {e}") from e
except requests.Timeout as e:
raise FojinUnavailableError(f"FoJin API timeout: {e}") from e
def test_connection(self) -> bool: def test_connection(self) -> bool:
"""Test if FoJin API is reachable.""" """Test if FoJin API is reachable."""
+9 -1
View File
@@ -16,7 +16,7 @@ import os
# Ensure tools/ is on the path so we can import fojin_bridge # Ensure tools/ is on the path so we can import fojin_bridge
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from fojin_bridge import create_bridge from fojin_bridge import create_bridge, FojinUnavailableError
def format_search_results(data: dict) -> str: def format_search_results(data: dict) -> str:
@@ -215,6 +215,14 @@ def main():
try: try:
args.func(args) args.func(args)
except FojinUnavailableError:
print("[FoJin API 当前不可用]")
print("无法检索真实经文。法师将仅基于预置 teaching.md 回答。")
print("建议:")
print("- 稍后重试")
print("- 检查网络连接")
print("- 或在 fojin.app 直接查阅原典")
sys.exit(0)
except ConnectionError as e: except ConnectionError as e:
print(f"[错误] 无法连接 FoJin API: {e}", file=sys.stderr) print(f"[错误] 无法连接 FoJin API: {e}", file=sys.stderr)
sys.exit(1) sys.exit(1)